View Full Version : RGBAdapt v0.5 plugin 06 Dec 2018
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)
Bernardd
16th June 2015, 18:43
Hi StainlessS,
Thank for explanation.
This day, i have used the graffer, and i have found a error conception for my script.
I have linked Rpow and Spow corrections. For little correction is not a real problem, but for big is not good.
I believe that i have smelt this problem, because i have put in the old script a pseudo gamma variable, which can be increase if neccessary.
With your graffer, i can analyze the process with a external view.
For gamma curve the RGB difference must be converted by formula pow(4.0, RGB difference) to give the gamma correction value.
With this formula, i can have similar power action in automated white balance and graffer white balance with bias and rpow args tunes.
But with this formula Rpow and Spow link is no good for little corrections.
Thus i have written a new version where the spow args are only manual. It is like a automated RGBAdjust with manual inflexion curves if necessary.
For normal video automated correction have a good look. For bad video add manual correction can be nice.
This day, now, i have not idea to automate Spow action.
function RGBAdapt_auto_awb_process(clip clip, bool "show_info", bool "matrix", float "linear_gamma_mix",\
bool "spow_action_enable",float "r_spow", float "g_spow", float "b_spow",\
float "r_spmid", float "g_spmid", float "b_spmid", bool "r_pord", bool "g_pord", bool "b_pord")
{
#----------------------------------------------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")
spow_action_enable = Default(spow_action_enable, false)
r_spow = Default(r_spow, 1.0) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(r_spow>=0.1 && r_spow <= 4.0,"RGBAdapt_auto_awb: spow 0.1 -> 4.0")
g_spow = Default(g_spow, 1.0) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(r_spow>=0.1 && g_spow <= 4.0,"RGBAdapt_auto_awb: spow 0.1 -> 4.0")
b_spow = Default(b_spow, 1.0) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(r_spow>=0.1 && b_spow <= 4.0,"RGBAdapt_auto_awb: spow 0.1 -> 4.0")
r_spmid = Default(r_spmid, 0.5) # it is original RGBADapt Channel_spmid args, range 0.1 to 0.99 center 0.5
Assert(r_spmid>=0.01 && r_spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
g_spmid = Default(g_spmid, 0.5)
Assert(g_spmid>=0.01 && g_spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
b_spmid = Default(b_spmid, 0.5)
Assert(b_spmid>=0.01 && b_spmid <= 0.99,"RGBAdapt_auto_awb: spmid 0.01 -> 0.99")
r_pord = Default(r_pord, false) # it is original RGBADapt Channel_pord args
g_pord = Default(g_pord, false)
b_pord = Default(b_pord, false)
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(4.0,dr_gamma/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(4.0,dg_gamma/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(4.0,db_gamma/128)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul
r_spow = (!spow_action_enable)? 1.0 : r_spow
g_spow = (!spow_action_enable)? 1.0 : g_spow
b_spow = (!spow_action_enable)? 1.0 : b_spow
#---------- 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 = r_spow, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = 0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = g_spow, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = 0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = b_spow, B_SPMid = b_spmid, B_Pord = b_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 = r_spow, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = dg_linear + dg_out*(1 -linear_gamma_mix), G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = g_spow, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = db_linear + db_out*(1 -linear_gamma_mix), B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = b_spow, B_SPMid = b_spmid, B_Pord = b_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)+" Iteration 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)+" Iteration 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)+" Iteration linear adjust : "+String(db_out)+\
"\nOutput Blue value : "+String(blue_out), y=340,lsp=20)\
.Subtitle("Luma value "+String(y), y=500)
""", args = "show_info, matrix,linear_gamma_mix,"+ \
"spow_action_enable, r_spow, g_spow, b_spow,"+\
"r_spmid, g_spmid, b_spmid, r_pord, g_pord, b_pord, standard")
}
kuchikirukia
17th June 2015, 03:19
Is this what I need to fix something like this:
http://s15.postimg.org/nzi02ub2f/ummm.jpg (http://postimg.org/image/nzi02ub2f/)
StainlessS
17th June 2015, 03:23
Cant do update just yet.
For some reason my VS6 compiler is producing code that results in access violations, only for release mode (not DEBUG)
and not when using VS ToolKit 2003. Narrowed it down to about 10 lines of code the only effect of which was to link in
an avisynth dll, and when called produce a ThrowError() error message, ie "env->ThrowError("TEST: This is a test error");".
Was managing to produce access violation before getting there. [EDIT: But only in some media players eg WMP, not Vdub].
Finally tried a compile on another machine and no error exception produced by resultant dll. (same VS6 compiler).
[EDIT: And tested on same machine that was producing original error.]
When I started using VB6 a few days back, it demanded that I give it the Platform SDK Disk to update, and I think it somehow
screwed my CPP compiler.
Anyways, looks like I might be doing a system recovery from stable image from a few months back, I post update as soon as I can.
If you would like to try out the (much improved I think) Graffer, here tis:- EDIT LINK REMOVED
EDIT: kuchikirukia, DL the graffer and load in the image provided, you will easily see if the dll can be of use
(should not be too long till I update, perhaps tomorrow as I could [and usually do] do final compile using VS ToolKit 2003
which is not affected by the problem I'm having. I have to get some sleep now as its 03:30AM).
EDIT: The image YOU provided.
StainlessS
17th June 2015, 04:19
k, here spent about two minutes playing with the sliders, you could do better.
Maybe start with about same settings Ive used and also play with SPMid settings.
I've used identical for R,G and B.
Before on the right, mod on the left. You do not have a lot to play with.
Here:-
https://s20.postimg.org/jdcjnez5p/kk_zps7axkbjlb.jpg (https://postimg.org/image/ym2h16su1/)
Gonna get some sleep now.
EDIT: The currently available dll has all args execept the bottom 4 (which are unlikely to be of use in this case).
You will want to reduce the lighter levels a bit from what I've used.
EDIT: If you do get a setting that you are happy with, post result here, I'de be interested to see what you can get out of the sample.
EDIT: I'll try to implement a Lock, so you can simultaneously set all channels the same, its real tricky one at a time.
EDIT: is it a single frame or video ?
Is camera stationary ?
Maybe need answer to both (well 2nd i video), so others could assist.
Perhaps needs some kind of mask if stationary or single frame, lighten audience and you screw with the stage lowlites.
StainlessS
17th June 2015, 19:52
RgbAdapt v0.3, dll and Graffer updates., see 1st post.
Added IMin, OMin, IMax, OMax args for each channel.
Now copies rather than zero Alpha channel (v0.2 no public release).
RGBAdapt v0.3, By StainlessS
For Avisynth v2.58+
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.)
EDIT: Added ALL Channel Locking to the Graffer for each RgbAdapt argument, change R & G and B simultaneously.
StainlessS
17th June 2015, 22:36
Here a better daft example what the Min/Max args could be used for (mask making) [frog not really part of example].
(not intended to do anything useful, just to show what you can do)
https://s20.postimg.cc/xxtmi8u4d/Frog_Min_Max_zpsbb2x9pld.jpg (https://postimg.cc/image/yal0ofce1/)
Also NOTE, RgbAdapt Graffer can be used with RgbAdjust (Bias[integer only], Gain and RPow only).
EDIT:Actually, Bias implemented already as Float in both dll and Graffer.
kuchikirukia
17th June 2015, 23:03
I'm thinking something like this, maybe.
http://s1.postimg.org/gjw6e5hvv/Untitled.jpg (http://postimg.org/image/gjw6e5hvv/)
Preview is too small to really tell and I have another encode going so I'm not ready to get on this in avisynth.
Source is actually a commercial Blu-ray. I think they killed the levels because they projected onto a glossy screen which gave a hilariously enlarged and distorted reflection of the audience. So Miku is performing in a sea of demonic red faces.
StainlessS
17th June 2015, 23:16
Preview is too small
Sorry bout dat, I struggled to make it fit 1024x768, and wanted a 512x512 graf
(which makes it actually a bit less smooth looking than if 256x256 [somewhat like point resize, sort of]).
EDIT: With 512x512 get better view when line in Dots/Bubbles style, to see jumps/gaps in LUT.
With 512x512 the graf consists of lots of little line segments without some overall formula (with rounding) to achieve
required curve. With 256x256, for the most part the lines can be up/down one pixel, left or right 1 pixel or
1 pixel 45 degree diagonal, looks quite smooth curve because of this.
jumps/gaps in LUT
See 2nd image @ post #49.
I was trying to bring out more of the audience, silly me :)
EDIT: It's not too difficult to copy the RgbAdapt function call to clipboard (via the Button) and CTRL/V paste into eg VDubMod
script editor and press VD refresh button to view in all its glory.
StainlessS
18th June 2015, 11:15
Also NOTE, RgbAdapt Graffer can be used with RgbAdjust (Bias[integer only], Gain and RPow only).
Actually I implemented as float in both dll and Graffer so Bias also identical for use of RgbAdjust via Graffer.
(dont know why, thought I'de done it as int in both dll and graffer).
EDIT: @ Bernardd
I see that you've left out all of the Float(Default()) floats again :(
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.
http://web.archive.org/web/20140315154448/http://img245.imageshack.us/img245/7905/coloryuv.gif
http://forum.doom9.org/showthread.php?t=154731
Bernardd
18th June 2015, 23:36
Hi StainlessS
Below, the last version. Default, white balance is automatic with Rpow curve. If it is not enought, first you can enable Spow curve (spmid and pord are auto), secund you can enable auto gain and cont args.
You have perhaps to choice the processed color channels by gain and cont. You can always mix classic awb (linear) with gamma awb (the only float(default) ;)).
You can also display the computed values to use as start values for RGBadapt manual use.
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.
Why you say that ? In script, i use once "BlankClip(output_video, pixel_type="RGB32", color=$000000)", only to extract RGB channels values.
This work is in RGB color space for compute in RGB color space, do you think it is an error ? I need time to digest these datas http://forum.doom9.org/showthread.php?t=154731
function RGBAdapt_auto_awb_process(clip clip, bool "show_info", bool "matrix", float "linear_gamma_mix", bool "booster_1",\
bool "booster_2", bool "booster_2_red_apply", bool "booster_2_green_apply", bool "booster_2_blue_apply")
{
#----------------------------------------------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 = 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")
booster_1 = Default(booster_1, false) # enable spow curve use
booster_2 = Default(booster_2, false) # enable gain and cont use
booster_2_red_apply = Default(booster_2_red_apply, false) # enable gain and cont use to red channel
booster_2_green_apply = Default(booster_2_green_apply, false) # enable gain and cont use to green channel
booster_2_blue_apply = Default(booster_2_blue_apply, false) # enable gain and cont use to blue channel
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(4.0,dr_gamma/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(4.0,dg_gamma/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(4.0,db_gamma/128)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul
sr = (!booster_1)? 1.0 : pow(4.0,dr_gamma/(256.0))
sr = Min (4.0, Max (sr, 0.1))
sg = (!booster_1)? 1.0 : pow(4.0,dg_gamma/(256.0))
sg = Min (4.0, Max (sg, 0.1))
sb = (!booster_1)? 1.0 : pow(4.0,db_gamma/(256.0))
sb = Min (4.0, Max (sb, 0.1))
#--------- Spmid calcul
r_spmid = 0.5 * sr
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = 0.5 * sg
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = 0.5 * sb
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#------- Pord calcul
r_pord = (sr < 1.0) ? true : false
g_pord = (sg < 1.0) ? true : false
b_pord = (sb < 1.0) ? true : false
#---------- 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 = r_spmid, R_Pord = r_pord,\
G_Bias = 0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = 0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_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)
y_out = red_out*kr+green_out*kg+blue_out*kb
#------- 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)
r_gain_out = (!booster_2) ? 0 : ((!booster_2_red_apply) ? 0 : dr_out/(red_out+r))
g_gain_out = (!booster_2) ? 0 : ((!booster_2_green_apply) ? 0 : dg_out/(green_out+g))
b_gain_out = (!booster_2) ? 0 : ((!booster_2_blue_apply) ? 0 : db_out/(blue_out+b))
r_cont_out = (!booster_2) ? 0 : ((!booster_2_red_apply) ? 0 : dr_out/(red_out+r))
g_cont_out = (!booster_2) ? 0 : ((!booster_2_green_apply) ? 0 : dg_out/(green_out+g))
b_cont_out = (!booster_2) ? 0 : ((!booster_2_blue_apply) ? 0 : db_out/(blue_out+b))
output_video = RGBAdapt( \
R_Bias = dr_linear + dr_out*(1 -linear_gamma_mix), R_Gain = 1.0 + r_gain_out, R_Cont = 1.0 + r_cont_out, \
R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = dg_linear + dg_out*(1 -linear_gamma_mix), G_Gain = 1.0 + g_gain_out, G_Cont = 1.0 + g_cont_out, \
G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = db_linear + db_out*(1 -linear_gamma_mix), B_Gain = 1.0 + b_gain_out, B_Cont = 1.0 + b_cont_out, \
B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#--------- secund pass output RGB values extraction to display
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)
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)+" Iteration linear adjust : "+String(dr_out)+\
"\nGamma curves correction base : "+String(dr_gamma)+\
"\nRpow : "+String(yr)+" Spow : "+String(sr)+" Spmid : "+String(r_spmid)+" Pord : "+String(r_pord)+\
"\nGain / Cont : "+String(r_gain_out)+ " Output 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)+" Iteration linear adjust : "+String(dg_out)+\
"\nGamma curves correction base : "+String(dg_gamma)+\
"\nRpow : "+String(yg)+" Spow : "+String(sg)+" Spmid : "+String(g_spmid)+" Pord : "+String(g_pord)+\
"\nGain / Cont : "+String(g_gain_out)+ " Output 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)+" Iteration linear adjust : "+String(db_out)+\
"\nGamma curves correction base : "+String(db_gamma)+\
"\nRpow : "+String(yb)+" Spow : "+String(sb)+" Spmid : "+String(b_spmid)+" Pord : "+String(b_pord)+\
"\nGain / Cont : "+String(b_gain_out)+ " Output Blue value : "+String(blue_out), y=340,lsp=20)\
.Subtitle("Luma value "+String(y)+" "+String(r_cont_out), y=500)
""", args = "show_info, matrix,linear_gamma_mix,booster_1,"+ \
"booster_2, booster_2_red_apply,booster_2_green_apply,booster_2_blue_apply")
}
StainlessS
19th June 2015, 15:00
Why you say that ?
Sorry, did not mean anything by that regarding current script, I had just stumbled across that (linked) web page and found the
gif animation (script by Gavino) and thought you might like it (if you had not already seen it).
Bernardd
27th June 2015, 19:18
Hi StainlessS,
Below the last version of script.
Now awb is result of automatic actions on bias, gain, cont, rpow, spow, spmid and pord.
This args are used and tuned in two silent pass. Thus gain, cont, rpow and spow are computed twice.
If the AWB look is not nice. First, we can disable the spow applications, which amplify white balance. Second, we can disable the second rpow application which amplify also white balance.
If it is not enough, we can decrease rpow and spow application strength, thus it is possible to keep a piece of sunset color. After, we can decrease gain and cont strength, but it is necessary when movie have fade in or fade out scene.
At end we can mix Classic AWB with this automatic white balance. We can always show computed args for manual RGBadapt start point use.
function RGBAdapt_auto_awb_process(clip clip, bool "show_info", string "matrix", bool "spow_use", bool "second_rpow_use", float "gamma_strength", float "gain_cont_strength", float "classic_smart_awb_mix")
{
#----------------------------------------------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 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
show_info = Default(show_info, false) # show info or not, default false
matrix = string(Default(matrix, "Rec601") )# Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
spow_use = Default(spow_use, true) # enable spow curve use
second_rpow_use = Default(second_rpow_use, true) # enable second rpow curve use
gamma_strength = Float(Default(gamma_strength, 4.0)) # linear curve use strength, between 1.0 and 4.0, default 4.0
Assert(gamma_strength>=1.0 && gamma_strength <= 4.0,"RGBAdapt_auto_awb: gamma_strength 1.0 -> 4.0")
gain_cont_strength = Float(Default(gain_cont_strength, 1.0)) # linear curve use strength, between 0.0 and 1.0, default 1.0
Assert(gain_cont_strength>=0.0 && gain_cont_strength <= 1.0,"RGBAdapt_auto_awb: gain_cont_strength 0.0 -> 1.0")
classic_smart_awb_mix = Float(Default(classic_smart_awb_mix, 0.0)) # linear curve use strength, between 0.0 and 1.0, default 0.0
Assert(classic_smart_awb_mix>=0.0 && classic_smart_awb_mix <= 1.0,"RGBAdapt_auto_awb: classic_smart_awb_mix 0.0 -> 1.0")
ScriptClip(clip, """
clip = last
#------------ Color matrix input
Kr = (matrix == "Rec601") ? 0.299 : 0.2126
Kg = (matrix == "Rec601") ? 0.587 : 0.7152
Kb = (matrix == "Rec601") ? 0.114 : 0.0722
#------------ YUV values extraction
(!isYV12(clip)) ? ConvertToYV12(clip, matrix=matrix) : 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 * classic_smart_awb_mix
dg_linear = dg * classic_smart_awb_mix
db_linear = db * classic_smart_awb_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_strength,dr_gamma/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(gamma_strength,dg_gamma/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(gamma_strength,db_gamma/128)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul
sr = (!spow_use)? 1.0 : pow(gamma_strength,dr_gamma/(256.0))
sr = Min (4.0, Max (sr, 0.1))
sg = (!spow_use)? 1.0 : pow(gamma_strength,dg_gamma/(256.0))
sg = Min (4.0, Max (sg, 0.1))
sb = (!spow_use)? 1.0 : pow(gamma_strength,db_gamma/(256.0))
sb = Min (4.0, Max (sb, 0.1))
#--------- Spmid calcul
r_spmid = 0.5 * sr
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = 0.5 * sg
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = 0.5 * sb
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#------- Pord calcul
r_pord = (sr < 1.0) ? true : false
g_pord = (sg < 1.0) ? true : false
b_pord = (sb < 1.0) ? true : false
#---------- RGBAdapt use
(!isRGB(clip)) ? ConvertToRGB24(last, matrix=matrix) : 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 = r_spmid, R_Pord = r_pord,\
G_Bias = 0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = 0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_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)*(1 -classic_smart_awb_mix) # experiment say necessary to insert luma channel factors
dg_out = (g_awb - green_out)*(1-kg)*(1 -classic_smart_awb_mix) # is to keep classic awb when classic_smart_awb_mix is 1
db_out = (b_awb - blue_out)*(1-kb)*(1 -classic_smart_awb_mix)
#----- Gain cont calcul
r_gain = gain_cont_strength*dr_gamma*(1-kr)/r # experiment say : not good idea to apply in first pass
g_gain = gain_cont_strength*dg_gamma*(1-kg)/g
b_gain = gain_cont_strength*db_gamma*(1-kb)/b
r_cont = gain_cont_strength*dr_gamma*(1-kr)/r
g_cont = gain_cont_strength*dg_gamma*(1-kg)/g
b_cont = gain_cont_strength*db_gamma*(1-kb)/b
r_gain_out = gain_cont_strength*dr_out/red_out
g_gain_out = gain_cont_strength*dg_out/green_out
b_gain_out = gain_cont_strength*db_out/blue_out
r_cont_out = gain_cont_strength*dr_out/red_out
g_cont_out = gain_cont_strength*dg_out/green_out
b_cont_out = gain_cont_strength*db_out/blue_out
final_r_gain = r_gain * r_gain_out
final_r_gain = Min (7.0, Max (final_r_gain, -7.0))
final_g_gain = g_gain * g_gain_out
final_g_gain = Min (7.0, Max (final_g_gain, -7.0))
final_b_gain = b_gain * b_gain_out
final_b_gain = Min (7.0, Max (final_b_gain, -7.0))
final_r_cont = r_cont * r_cont_out
final_r_cont = Min (7.0, Max (final_r_cont, -7.0))
final_g_cont = g_cont * g_cont_out
final_g_cont = Min (7.0, Max (final_g_cont, -7.0))
final_b_cont = b_cont * b_cont_out
final_b_cont = Min (7.0, Max (final_b_cont, -7.0))
#----- Final rpow calcul
yr_out = (!second_rpow_use)? 1.0 : pow(gamma_strength,dr_out/(128.0))
yr_out = Min (4.0, Max (yr_out, 0.1))
yg_out = (!second_rpow_use)? 1.0 : pow(gamma_strength,dg_out/(128.0))
yg_out = Min (4.0, Max (yg_out, 0.1))
yb_out = (!second_rpow_use)? 1.0 : pow(gamma_strength,db_out/(128.0))
yb_out = Min (4.0, Max (yb_out, 0.1))
yr = yr * yr_out
yg = yg * yg_out
yb = yb * yb_out
#----- Final spow calcul
sr_out = (!spow_use)? 1.0 : pow(gamma_strength,dr_out/(256.0))
sr_out = Min (4.0, Max (sr_out, 0.1))
sg_out = (!spow_use)? 1.0 : pow(gamma_strength,dg_out/(256.0))
sg_out = Min (4.0, Max (sg_out, 0.1))
sb_out = (!spow_use)? 1.0 : pow(gamma_strength,db_out/(256.0))
sb_out = Min (4.0, Max (sb_out, 0.1))
#--------- Spmid calcul
r_spmid_out = 0.5 * sr_out
r_spmid_out = Min (0.99, Max (r_spmid_out, 0.01))
g_spmid_out = 0.5 * sg_out
g_spmid_out = Min (0.99, Max (g_spmid_out, 0.01))
b_spmid_out = 0.5 * sb_out
b_spmid_out = Min (0.99, Max (b_spmid_out, 0.01))
sr = sr * sr_out
sg = sg * sg_out
sb = sb * sb_out
r_spmid = r_spmid * r_spmid_out
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = g_spmid * g_spmid_out
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = b_spmid * b_spmid_out
b_spmid = Min (0.99, Max (b_spmid, 0.01))
output_video = RGBAdapt( \
R_Bias = dr_linear + dr_out, R_Gain = 1.0 + final_r_gain, R_Cont = 1.0 + final_r_cont, \
R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = dg_linear + dg_out, G_Gain = 1.0 + final_g_gain, G_Cont = 1.0 + final_g_cont, \
G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = db_linear + db_out, B_Gain = 1.0 + final_b_gain, B_Cont = 1.0 + final_b_cont, \
B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#--------- second pass output RGB values extraction to display
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)
output_video = (!isRGB(clip)) ? ConvertToYV12(output_video, matrix=matrix) : 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)+" Iteration linear adjust : "+String(dr_out)+\
"\nGamma curves correction base : "+String(dr_gamma)+\
"\nRpow : "+String(yr)+" Spow : "+String(sr)+" Spmid : "+String(r_spmid)+" Pord : "+String(r_pord)+\
"\nGain / Cont : "+String(final_r_gain)+ " Output 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)+" Iteration linear adjust : "+String(dg_out)+\
"\nGamma curves correction base : "+String(dg_gamma)+\
"\nRpow : "+String(yg)+" Spow : "+String(sg)+" Spmid : "+String(g_spmid)+" Pord : "+String(g_pord)+\
"\nGain / Cont : "+String(final_g_gain)+ " Output 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)+" Iteration linear adjust : "+String(db_out)+\
"\nGamma curves correction base : "+String(db_gamma)+\
"\nRpow : "+String(yb)+" Spow : "+String(sb)+" Spmid : "+String(b_spmid)+" Pord : "+String(b_pord)+\
"\nGain / Cont : "+String(final_b_gain)+ " Output Blue value : "+String(blue_out), y=340,lsp=20)\
.Subtitle("Luma value "+String(y)+" "+String(r_cont_out), y=500)
""", args = "show_info,matrix,spow_use,second_rpow_use,gamma_strength,gain_cont_strength,classic_smart_awb_mix")
}
Bernardd
30th June 2015, 00:11
Hi StainlessS
A new version with just some brackets and one variable name adjusted. (Second_rpow_use is now rpow_spow_adjust)
function RGBAdapt_auto_awb_process(clip clip, bool "show_info", string "matrix", bool "spow_use", \
bool "rpow_spow_adjust", float "gamma_strength", float "gain_cont_strength", float "classic_smart_awb_mix")
{
#----------------------------------------------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 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
show_info = Default(show_info, false) # show info or not, default false
matrix = string(Default(matrix, "Rec601") )# Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
spow_use = Default(spow_use, true) # enable spow curve use
rpow_spow_adjust = Default(rpow_spow_adjust, true) # enable rpow and spow adjustcurve use
gamma_strength = Float(Default(gamma_strength, 4.0)) # linear curve use strength, between 1.0 and 8.0, default 4.0, above 4.0 it is to get nice color with very bad videos
Assert(gamma_strength>=1.0 && gamma_strength <= 8.0,"RGBAdapt_auto_awb: gamma_strength 1.0 -> 4.0")
gain_cont_strength = Float(Default(gain_cont_strength, 1.0)) # linear curve use strength, between 0.0 and 1.0, default 1.0
Assert(gain_cont_strength>=0.0 && gain_cont_strength <= 1.0,"RGBAdapt_auto_awb: gain_cont_strength 0.0 -> 1.0")
classic_smart_awb_mix = Float(Default(classic_smart_awb_mix, 0.0)) # linear curve use strength, between 0.0 and 1.0, default 0.0
Assert(classic_smart_awb_mix>=0.0 && classic_smart_awb_mix <= 1.0,"RGBAdapt_auto_awb: classic_smart_awb_mix 0.0 -> 1.0")
ScriptClip(clip, """
clip = last
#------------ Color matrix input
Kr = (matrix == "Rec601") ? 0.299 : 0.2126
Kg = (matrix == "Rec601") ? 0.587 : 0.7152
Kb = (matrix == "Rec601") ? 0.114 : 0.0722
#------------ YUV values extraction
(!isYV12(clip)) ? ConvertToYV12(clip, matrix=matrix) : 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_classic = dr * classic_smart_awb_mix
dg_classic = dg * classic_smart_awb_mix
db_classic = db * classic_smart_awb_mix
#---------- Remaining RGB correction after classic linear curve process
dr_gamma = dr - dr_classic
dg_gamma = dg - dg_classic
db_gamma = db - db_classic
#----------- RGB correction with Rpow curve calcul
yr = pow(gamma_strength,dr_gamma/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(gamma_strength,dg_gamma/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(gamma_strength,db_gamma/128)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul
sr = (!spow_use)? 1.0 : pow(gamma_strength,dr_gamma/256.0)
sr = Min (4.0, Max (sr, 0.1))
sg = (!spow_use)? 1.0 : pow(gamma_strength,dg_gamma/256.0)
sg = Min (4.0, Max (sg, 0.1))
sb = (!spow_use)? 1.0 : pow(gamma_strength,db_gamma/256.0)
sb = Min (4.0, Max (sb, 0.1))
#--------- Spmid calcul
r_spmid = 0.5 * sr
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = 0.5 * sg
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = 0.5 * sb
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#------- Pord calcul
r_pord = (sr < 1.0) ? true : false
g_pord = (sg < 1.0) ? true : false
b_pord = (sb < 1.0) ? true : false
#---------- RGBAdapt use
(!isRGB(clip)) ? ConvertToRGB24(last, matrix=matrix) : 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 = r_spmid, R_Pord = r_pord,\
G_Bias = 0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = 0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_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)*(1 -classic_smart_awb_mix) # experiment say necessary to insert luma channel factors
dg_out = (g_awb - green_out)*(1-kg)*(1 -classic_smart_awb_mix) # is to keep classic awb when classic_smart_awb_mix is 1
db_out = (b_awb - blue_out)*(1-kb)*(1 -classic_smart_awb_mix)
#----- Gain cont calcul
r_gain = gain_cont_strength*dr_gamma*(1-kr)/r # experiment say : not good idea to apply in first pass
g_gain = gain_cont_strength*dg_gamma*(1-kg)/g
b_gain = gain_cont_strength*db_gamma*(1-kb)/b
r_cont = gain_cont_strength*dr_gamma*(1-kr)/r
g_cont = gain_cont_strength*dg_gamma*(1-kg)/g
b_cont = gain_cont_strength*db_gamma*(1-kb)/b
r_gain_out = gain_cont_strength*dr_out/red_out
g_gain_out = gain_cont_strength*dg_out/green_out
b_gain_out = gain_cont_strength*db_out/blue_out
r_cont_out = gain_cont_strength*dr_out/red_out
g_cont_out = gain_cont_strength*dg_out/green_out
b_cont_out = gain_cont_strength*db_out/blue_out
final_r_gain = r_gain * r_gain_out
final_r_gain = Min (7.0, Max (final_r_gain, -7.0))
final_g_gain = g_gain * g_gain_out
final_g_gain = Min (7.0, Max (final_g_gain, -7.0))
final_b_gain = b_gain * b_gain_out
final_b_gain = Min (7.0, Max (final_b_gain, -7.0))
final_r_cont = r_cont * r_cont_out
final_r_cont = Min (7.0, Max (final_r_cont, -7.0))
final_g_cont = g_cont * g_cont_out
final_g_cont = Min (7.0, Max (final_g_cont, -7.0))
final_b_cont = b_cont * b_cont_out
final_b_cont = Min (7.0, Max (final_b_cont, -7.0))
#----- Final rpow calcul
yr_out = (!rpow_spow_adjust)? 1.0 : pow(gamma_strength,dr_out/128.0)
yr_out = Min (4.0, Max (yr_out, 0.1))
yg_out = (!rpow_spow_adjust)? 1.0 : pow(gamma_strength,dg_out/128.0)
yg_out = Min (4.0, Max (yg_out, 0.1))
yb_out = (!rpow_spow_adjust)? 1.0 : pow(gamma_strength,db_out/128.0)
yb_out = Min (4.0, Max (yb_out, 0.1))
yr = yr * yr_out
yg = yg * yg_out
yb = yb * yb_out
#----- Final spow calcul
sr_out = (!rpow_spow_adjust)? 1.0 : ((!spow_use)? 1.0 : pow(gamma_strength,dr_out/256.0))
sr_out = Min (4.0, Max (sr_out, 0.1))
sg_out = (!rpow_spow_adjust)? 1.0 : ((!spow_use)? 1.0 : pow(gamma_strength,dg_out/256.0))
sg_out = Min (4.0, Max (sg_out, 0.1))
sb_out = (!rpow_spow_adjust)? 1.0 : ((!spow_use)? 1.0 : pow(gamma_strength,db_out/256.0))
sb_out = Min (4.0, Max (sb_out, 0.1))
#--------- Spmid calcul
r_spmid_out = 0.5 * sr_out
r_spmid_out = Min (0.99, Max (r_spmid_out, 0.01))
g_spmid_out = 0.5 * sg_out
g_spmid_out = Min (0.99, Max (g_spmid_out, 0.01))
b_spmid_out = 0.5 * sb_out
b_spmid_out = Min (0.99, Max (b_spmid_out, 0.01))
sr = sr * sr_out
sg = sg * sg_out
sb = sb * sb_out
r_spmid = r_spmid * r_spmid_out
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = g_spmid * g_spmid_out
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = b_spmid * b_spmid_out
b_spmid = Min (0.99, Max (b_spmid, 0.01))
output_video = RGBAdapt( \
R_Bias = dr_classic + dr_out, R_Gain = 1.0 + final_r_gain, R_Cont = 1.0 + final_r_cont, \
R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = dg_classic + dg_out, G_Gain = 1.0 + final_g_gain, G_Cont = 1.0 + final_g_cont, \
G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = db_classic + db_out, B_Gain = 1.0 + final_b_gain, B_Cont = 1.0 + final_b_cont, \
B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#--------- second pass output RGB values extraction to display
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)
output_video = (!isRGB(clip)) ? ConvertToYV12(output_video, matrix=matrix) : 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_classic)+" Iteration linear adjust : "+String(dr_out)+\
"\nGain / Cont : "+String(final_r_gain)+\
"\nGamma curves correction base : "+String(dr_gamma)+\
"\nRpow : "+String(yr)+" Spow : "+String(sr)+" Spmid : "+String(r_spmid)+" Pord : "+String(r_pord)+\
"\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_classic)+" Iteration linear adjust : "+String(dg_out)+\
"\nGain / Cont : "+String(final_g_gain)+\
"\nGamma curves correction base : "+String(dg_gamma)+\
"\nRpow : "+String(yg)+" Spow : "+String(sg)+" Spmid : "+String(g_spmid)+" Pord : "+String(g_pord)+\
"\nOutput Green value : "+String(green_out),y=200,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_classic)+" Iteration linear adjust : "+String(db_out)+\
"\nGain / Cont : "+String(final_b_gain)+\
"\nGamma curves correction base : "+String(db_gamma)+\
"\nRpow : "+String(yb)+" Spow : "+String(sb)+" Spmid : "+String(b_spmid)+" Pord : "+String(b_pord)+\
"\nOutput Blue value : "+String(blue_out), y=360,lsp=20)
""", args = "show_info,matrix,spow_use,rpow_spow_adjust,gamma_strength,gain_cont_strength,classic_smart_awb_mix")
}
fvisagie
4th July 2015, 13:45
@StainlessS,
This plugin looks very comprehensive. How would one characterise RGBAdapt() - RGBAdjust() with added controls for curve shape and inflection points? Anything else/less?
Does it do anything specific to avoid banding, like dithering/high bitdepth processing?
Thanks,
François
StainlessS
4th July 2015, 14:17
RGBAdjust() with added controls for curve shape and inflection points
That just about covers it. All it does is create 3 LUT's and replace existing channel values with those from the LUT.
(As RgbAdjust or Levels, or ColorYUV).
fvisagie
5th July 2015, 08:43
Thanks much.
Bernardd
8th July 2015, 13:09
Hi StainlessS
Below the last script version. Only five args to tune Automatic white balance with RGBAdapt.
function RGBAdapt_auto_awb_process(clip clip, bool "show_info", string "matrix", float "gamma_strength", bool "spow_use", \
float "gain_cont_strength", float "cont_tune", float "bias_strength")
{
#----------------------------------------------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 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
show_info = Default(show_info, false) # show info or not, default false
matrix = string(Default(matrix, "Rec601") )# Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
gamma_strength = Float(Default(gamma_strength, 4.0)) # linear curve use strength, between 1.0 and 4.0,
Assert(gamma_strength>=1.0 && gamma_strength <= 4.0,"RGBAdapt_auto_awb: gamma_strength 1.0 -> 4.0")
spow_use = Default(spow_use, true) # enable spow curve use
gain_cont_strength = Float(Default(gain_cont_strength, 1.0)) # linear gain and cont curve use strength, between 0.0 and 1.0,
Assert(gain_cont_strength>=0.0 && gain_cont_strength <= 1.0,"RGBAdapt_auto_awb: gain_cont_strength 0.0 -> 1.0")
cont_tune = Float(Default(cont_tune, 0.0)) # cont curve use tune, between -1.0 and 1.0,
Assert(cont_tune>=-1.0 && cont_tune <= 1.0,"RGBAdapt_auto_awb: cont_tune 0.0 -> 1.0")
bias_strength = Float(Default(bias_strength, 1.0)) # bias curves correction strength
Assert(bias_strength>=0.0 && bias_strength <= 1.0,"RGBAdapt_auto_awb: bias_strength 0.0 -> 1.0")
ScriptClip(clip, """
clip = last
#------------ Color matrix input
Kr = (matrix == "Rec601") ? 0.299 : 0.2126
Kg = (matrix == "Rec601") ? 0.587 : 0.7152
Kb = (matrix == "Rec601") ? 0.114 : 0.0722
#------------ YUV values extraction
(!isYV12(clip)) ? ConvertToYV12(clip, matrix=matrix) : 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
#----------- RGB correction with Rpow curve calcul
yr = pow(gamma_strength,dr/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(gamma_strength,dg/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(gamma_strength,db/128)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul
sr = (!spow_use)? 1.0 : pow(gamma_strength,dr/256.0)
sr = Min (4.0, Max (sr, 0.1))
sg = (!spow_use)? 1.0 : pow(gamma_strength,dg/256.0)
sg = Min (4.0, Max (sg, 0.1))
sb = (!spow_use)? 1.0 : pow(gamma_strength,db/256.0)
sb = Min (4.0, Max (sb, 0.1))
#--------- Spmid calcul
r_spmid = 0.5 * sr
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = 0.5 * sg
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = 0.5 * sb
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#------- Pord calcul
r_pord = (sr < 1.0) ? true : false
g_pord = (sg < 1.0) ? true : false
b_pord = (sb < 1.0) ? true : false
#---------- first pass : process only with gamma curves
(!isRGB(clip)) ? ConvertToRGB24(last, matrix=matrix) : clip
output_video = RGBAdapt( \
R_Bias = 0, R_Gain = 1.0, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = 0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = 0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#----------- Gain Cont calcul
#----------- RGB values extraction
black = BlankClip(output_video, pixel_type="RGB24", color=$000000)
red = ShowRed(output_video,pixel_type="RGB24")
green = ShowGreen(output_video,pixel_type="RGB24")
blue = ShowBlue(output_video,pixel_type="RGB24")
red = RGBDifference(red, black)
green = RGBDifference(green, black)
blue = RGBDifference(blue, black)
dr_gain = (r_awb - red)
dg_gain = (g_awb - green)
db_gain = (b_awb - blue)
r_gain = 1.0 + gain_cont_strength*dr_gain/r
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = 1.0 + gain_cont_strength*dg_gain/g
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = 1.0 + gain_cont_strength*db_gain/b
b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = 1.0 + gain_cont_strength*dr_gain*cont_tune/r
r_cont = Min (8.0, Max (r_cont, -8.0))
g_cont = 1.0 + gain_cont_strength*dg_gain*cont_tune/g
g_cont = Min (8.0, Max (g_cont, -8.0))
b_cont = 1.0 + gain_cont_strength*db_gain*cont_tune/b
b_cont = Min (8.0, Max (b_cont, -8.0))
#---------- second pass : process only with gamma curves and gain cont linear curve
output_video = RGBAdapt( \
R_Bias = 0, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = 0, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = 0, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#----- Bias calcul
#----------- RGB values extraction
red = ShowRed(output_video,pixel_type="RGB24")
green = ShowGreen(output_video,pixel_type="RGB24")
blue = ShowBlue(output_video,pixel_type="RGB24")
red = RGBDifference(red, black)
green = RGBDifference(green, black)
blue = RGBDifference(blue, black)
dr_bias = (r_awb - red)*bias_strength
dg_bias = (g_awb - green) *bias_strength
db_bias = (b_awb - blue)*bias_strength
output_video = RGBAdapt( \
R_Bias = dr_bias, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = dg_bias, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = db_bias, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#--------- Final output RGB values extraction for display
red = ShowRed(output_video,pixel_type="RGB24")
green = ShowGreen(output_video,pixel_type="RGB24")
blue = ShowBlue(output_video,pixel_type="RGB24")
red_out = RGBDifference(red, black)
green_out = RGBDifference(green, black)
blue_out = RGBDifference(blue, black)
output_video = (!isRGB(clip)) ? ConvertToYV12(output_video, matrix=matrix) : 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)+\
"\nRpow : "+String(yr)+" Spow : "+String(sr)+" Spmid : "+String(r_spmid)+" Pord : "+String(r_pord)+\
"\nGain : "+String(r_gain)+" Cont : "+String(r_cont)+\
"\nBias correction : "+String(dr_bias)+\
"\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)+\
"\nRpow : "+String(yg)+" Spow : "+String(sg)+" Spmid : "+String(g_spmid)+" Pord : "+String(g_pord)+\
"\nGain : "+String(g_gain)+" Cont : "+String(g_cont)+\
"\nBias correction : "+String(dg_bias)+\
"\nOutput Green value : "+String(green_out),y=200,lsp=20)\
.Subtitle("Blue value : "+String(b)+" Target Blue awb value : "+String(b_awb)+\
"\nBlue Values Diff : "+String(db)+\
"\nRpow : "+String(yb)+" Spow : "+String(sb)+" Spmid : "+String(b_spmid)+" Pord : "+String(b_pord)+\
"\nGain : "+String(b_gain)+" Cont : "+String(b_cont)+\
"\nBias correction : "+String(db_bias)+\
"\nOutput Blue value : "+String(blue_out), y=360,lsp=20)
""", args = "show_info, matrix, gamma_strength, spow_use,gain_cont_strength, cont_tune, bias_strength")
}
StainlessS
8th July 2015, 15:53
Sorry for not answering pervious post Bernardd, your scripts usually do-my-head-in a bit, I usually need time to psych myself up :)
EDIT: above mis-spelling nearly got corrected but I liked it so much that I left it.
First line not intended to disparage your scripting, just the maths involved is hard work for me.
I'll take a peek when I get the chance. Thanks.
ssS
Bernardd
8th July 2015, 23:14
Dont be sorry. I understand uninterest to analyse script formulas which change every day. I have tried everything or a lot of else, before i did the right thing. Thanks for your patience.
Bernard
Bernardd
21st July 2015, 10:17
Hello StainlessS
RGBAdapt have not dither process like RGBAdjust. I do not know or see the RGBAdjust dither action power on video output, but i understand that dither give best datas.
Do you think that dither may change my script result ?
Bernard
StainlessS
25th July 2015, 15:19
Hi there B,
was not even aware that RGBAdjust has had the dither arg added for v2.6, dont think I'll bother adding similar to RGBAdapt.
Dither results would perhaps only reduce banding (if any) produced by your function.
Bernardd
26th July 2015, 22:35
Thanks StainlessS,
To day I have not seen banding artefacts, thus no problem, dither is not necessary.
StainlessS
28th July 2015, 13:36
@Bernardd, did it anyway :)
RGBAdapt v0.4 Beta. http://www.mediafire.com/download/75l9095p51q287a/RGBAdapt_dll_v0.4-20150728%28BETA%29.zip
Added RGBAdapt16().
Would someone that uses Dither like to give it a whirl.
RGBAdapt v0.4, By StainlessS
For Avisynth v2.58+
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
Reel.Deel
28th July 2015, 15:03
Hi there StainlessS, just gave RGBAdapt16 a quick try. Seems to be working fine. Here's how to dither back to 8-bit RGB using DitherPost (http://avisynth.nl/index.php/Dither_tools#DitherPost).
RGBAdapt16(R_SPow=1.2,G_SPow=1.2,B_SPow=1.2)
r = ShowRed("Y8").DitherPost()
g = ShowGreen("Y8").DitherPost()
b = ShowBlue("Y8").DitherPost()
MergeRGB(r,g,b)
StainlessS
28th July 2015, 15:11
Lovely Jubbly ol chum,
Think I'll leave Beta for a few days and then declare non-beta.
Not really much to go wrong with it. I shall steal your sample code for doc.
Reel.Deel
28th July 2015, 15:23
BTW, I was trying to use RgbAdapt_Graffer.exe but I got this error:
RgbAdapt_Graffer: Component 'comdlg32.ocx' or one of its dependencies not correctly registered: a file is missing or invalid
Did a quick Google search and found this thread (http://www.sevenforums.com/bsod-help-support/59463-comdlg32-ocx.html#post711841). Downloaded comdlg32.zip and placed Comdlg32.ocx in the same folder as RgbAdapt_Graffer.exe and voila, it worked.
Just thought I'd share just in case someone else encounters the same problem. My OS in Windows 7 64-bit.
StainlessS
28th July 2015, 15:35
Thnx RD,
Not sure, thought that was standard either in XP or installed with VB6 runtimes.
and post from M$:- http://answers.microsoft.com/en-us/windows/forum/windows_vista-windows_programs/how-to-fix-compnent-comctl32ocx-oe-one-of-its/36bb66d8-d7ba-475d-a2af-9aa4852e1c8e?auth=1
if people prefer official M$ link.
something else for the doc, ta very much :)
EDIT: Actually, not official M$ link but posted by MS MVP (Most Valued Professional, I think, eg MS tutor).
Bernardd
29th July 2015, 08:21
Hi StainlessS,
Sorry for hidden work tentation in my last question.
But always well done !
I have tried, my script give same result with RGBadapt or RGBadapt16.
Thanks.
StainlessS
29th July 2015, 08:34
Bernardd, no need for any sorrow, it was quite easy to implement and only took about 1 or maybe 1.5 hours to do conversion
and is probably of some use to others. Better to implement for Dither() rather than built-in dithering so as to benefit from
differing Dither() modes eg Floyd etc, also allows for further 16 bit processing prior to dither.
I shall probably add similar to ColorYUV2() at some point.
Be gud.
Bernardd
6th August 2015, 23:41
Hello Stainless
Below a new version.
I have added a luma automatic gain. It is autogain of ColorYUV calcul but use in RGBAdapt.
function RGBAdapt_auto_awb_process(clip clip, bool "show_info", string "matrix", float "threshold", float "luma_autogain_strength",\
float "gain_strength", float "cont_tune", float "gamma_strength", bool "spow_use",\
float "bias_strength")
{
#----------------------------------------------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 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
show_info = Default(show_info, false) # show info or not, default false
matrix = string(Default(matrix, "Rec601") )# Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
gamma_strength = Float(Default(gamma_strength, 2.0)) # linear curve use strength, between 1.0 and 4.0,
Assert(gamma_strength>=1.0 && gamma_strength <= 4.0,"RGBAdapt_auto_awb: gamma_strength 1.0 -> 4.0")
spow_use = Default(spow_use, true) # enable spow curve use
threshold = Float(Default(threshold, 0.00)) # threshold arg of Y, u anv V plane AviSynth runtime functions
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.0 -> 1.0")
luma_autogain_strength = Float(Default(luma_autogain_strength, 0.5)) # luma_autogain_strength autogain strength, between 0.0 and 1.0
Assert(luma_autogain_strength>=0.0 && luma_autogain_strength <= 1.0,"RGBAdapt_auto_awb: luma_autogain_strength 0.0 -> 1.0")
gain_strength = Float(Default(gain_strength, 0.5)) # linear gain and cont curve use strength, between 0.0 and 1.0,
Assert(gain_strength>=0.0 && gain_strength <= 4.0,"RGBAdapt_auto_awb: gain_strength 0.0 -> 3.0")
cont_tune = Float(Default(cont_tune, 0.5)) # cont curve use tune, between -1.0 and 1.0,
Assert(cont_tune>=-4.0 && cont_tune <= 4.0,"RGBAdapt_auto_awb: cont_tune -3.0 -> 3.0")
bias_strength = Float(Default(bias_strength, 0.5)) # bias curves correction strength
Assert(bias_strength>=0.0 && bias_strength <= 1.0,"RGBAdapt_auto_awb: bias_strength 0.0 -> 1.0")
ScriptClip(clip, """
clip = last
#------------ Color matrix input
Kr = (matrix == "Rec601") ? 0.299 : 0.2126
Kg = (matrix == "Rec601") ? 0.587 : 0.7152
Kb = (matrix == "Rec601") ? 0.114 : 0.0722
#------------ YUV values extraction
(!isYV12(clip)) ? ConvertToYV12(clip, matrix=matrix) : clip
y = Averageluma()
u = AverageChromaU()
v = AverageChromaV()
y_max = YPlaneMax(threshold = threshold)
y_max = min (y_max, 235.0)
y_min = YPlaneMin(threshold = threshold)
y_min = max (16.0, y_min)
#----------- Automatic Y gain corrections calcul
#----------- Y autogain calcul
range_min_max = y_max - y_min
range_min_max = Max (range_min_max, 1.0)
f = float(219.0/range_min_max)
f = 1.0 + (f-1.0)*luma_autogain_strength
f = Min (3.4, Max (f, 0.0)) # to avoid below error message :
# Avisynth: access violation at 0x000496FD in C:\Windows\system32\Kernel32.dll,
# attempting to write to 0x595E308D
#----------- Y offset calcul
new_y_min = y_min * f
dy = (y_min - new_y_min)*luma_autogain_strength
#---------- 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+dy)*255.0/219 + 2*(v_awb-128)*255.0/224*(1-Kr) # Autogain offset luma is include here
g_awb = (y-16+dy)*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+dy)*255.0/219 + 2*(u_awb-128)*255.0/224*(1-Kb)
#---------- First pass : process with gamma curves
#----------- RGB corrections values calcul
dr = (r_awb - r)
dg = (g_awb - g)
db = (b_awb - b)
#----------- RGB correction with Rpow curve calcul
yr = pow(gamma_strength,dr/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(gamma_strength,dg/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(gamma_strength,db/128)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul
sr = (!spow_use)? 1.0 : pow(gamma_strength,dr/256.0)
sr = Min (4.0, Max (sr, 0.1))
sg = (!spow_use)? 1.0 : pow(gamma_strength,dg/256.0)
sg = Min (4.0, Max (sg, 0.1))
sb = (!spow_use)? 1.0 : pow(gamma_strength,db/256.0)
sb = Min (4.0, Max (sb, 0.1))
#--------- Spmid calcul
r_spmid = 0.5 * sr
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = 0.5 * sg
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = 0.5 * sb
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#------- Pord calcul
r_pord = (sr < 1.0) ? true : false
g_pord = (sg < 1.0) ? true : false
b_pord = (sb < 1.0) ? true : false
(!isRGB(clip)) ? ConvertToRGB24(last, matrix=matrix) : clip
output_video = RGBAdapt( \
R_Bias = 0, R_Gain = 1.0, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = 0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = 0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#---------- Second pass : process only with gain and cont curves
#----------- RGB values extraction
black = BlankClip(output_video, pixel_type="RGB24", color=$000000)
red = ShowRed(output_video,pixel_type="RGB24")
green = ShowGreen(output_video,pixel_type="RGB24")
blue = ShowBlue(output_video,pixel_type="RGB24")
red = RGBDifference(red, black)
green = RGBDifference(green, black)
blue = RGBDifference(blue, black)
#----------- RGB corrections calcul
dr_gain = r_awb - red
dg_gain = g_awb - green
db_gain = b_awb - blue
#---------- Gain calcul, autogain offset luma is include here
r_gain = f + gain_strength*dr_gain/r
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = f + gain_strength*dg_gain/g
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = f + gain_strength*db_gain/b
b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = 1.0 + dr_gain*cont_tune/r
r_cont = Min (8.0, Max (r_cont, -8.0))
g_cont = 1.0 + dg_gain*cont_tune/g
g_cont = Min (8.0, Max (g_cont, -8.0))
b_cont = 1.0 + db_gain*cont_tune/b
b_cont = Min (8.0, Max (b_cont, -8.0))
output_video = RGBAdapt( \
R_Bias = 0, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = 0, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = 0, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#---------- Third pass : process with bias curve
#----------- RGB values extraction
red = ShowRed(output_video,pixel_type="RGB24")
green = ShowGreen(output_video,pixel_type="RGB24")
blue = ShowBlue(output_video,pixel_type="RGB24")
red = RGBDifference(red, black)
green = RGBDifference(green, black)
blue = RGBDifference(blue, black)
#----------- RGB corrections calcul
dr_bias = (r_awb - red)*bias_strength
dg_bias = (g_awb - green) *bias_strength
db_bias = (b_awb - blue)*bias_strength
output_video = RGBAdapt( \
R_Bias = dr_bias, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = dg_bias, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = db_bias, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#--------- Final output RGB values extraction for display
red = ShowRed(output_video,pixel_type="RGB24")
green = ShowGreen(output_video,pixel_type="RGB24")
blue = ShowBlue(output_video,pixel_type="RGB24")
red_out = RGBDifference(red, black)
green_out = RGBDifference(green, black)
blue_out = RGBDifference(blue, black)
output_video = (!isRGB(clip)) ? ConvertToYV12(output_video, matrix=matrix) : output_video
#-------- displayed info or no
(!show_info)? output_video : output_video\
.Subtitle("Y value : "+String(Y)+" Y autogain : "+String(f),y=40)\
.Subtitle("Red value : "+String(r)+" Target Red awb value : "+String(r_awb)+\
"\nRed Values Diff : "+String(dr)+\
"\nRpow : "+String(yr)+" Spow : "+String(sr)+" Spmid : "+String(r_spmid)+" Pord : "+String(r_pord)+\
"\nGain : "+String(r_gain)+" Cont : "+String(r_cont)+\
"\nBias correction : "+String(dr_bias)+\
"\nOutput Red value : "+String(red_out),y=70,lsp=20)\
.Subtitle("Green value : "+String(g)+" Target Green awb value : "+String(g_awb)+\
"\nGreen Values Diff : "+String(dg)+\
"\nRpow : "+String(yg)+" Spow : "+String(sg)+" Spmid : "+String(g_spmid)+" Pord : "+String(g_pord)+\
"\nGain : "+String(g_gain)+" Cont : "+String(g_cont)+\
"\nBias correction : "+String(dg_bias)+\
"\nOutput Green value : "+String(green_out),y=210,lsp=20)\
.Subtitle("Blue value : "+String(b)+" Target Blue awb value : "+String(b_awb)+\
"\nBlue Values Diff : "+String(db)+\
"\nRpow : "+String(yb)+" Spow : "+String(sb)+" Spmid : "+String(b_spmid)+" Pord : "+String(b_pord)+\
"\nGain : "+String(b_gain)+" Cont : "+String(b_cont)+\
"\nBias correction : "+String(db_bias)+\
"\nOutput Blue value : "+String(blue_out), y=350,lsp=20)
""", args = "show_info, matrix, threshold, luma_autogain_strength, gain_strength, cont_tune, gamma_strength, spow_use, bias_strength")
}
Bernardd
7th August 2015, 09:17
Hello StainlessS
After night, a new version with best integration of luma autogain biais.
function RGBAdapt_auto_awb_process(clip clip, bool "show_info", string "matrix", float "threshold", float "luma_autogain_strength",\
float "gain_strength", float "cont_tune", float "gamma_strength", bool "spow_use",\
float "bias_strength")
{
#----------------------------------------------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 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
show_info = Default(show_info, false) # show info or not, default false
matrix = string(Default(matrix, "Rec601") )# Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
gamma_strength = Float(Default(gamma_strength, 2.0)) # linear curve use strength, between 1.0 and 4.0,
Assert(gamma_strength>=1.0 && gamma_strength <= 4.0,"RGBAdapt_auto_awb: gamma_strength 1.0 -> 4.0")
spow_use = Default(spow_use, true) # enable spow curve use
threshold = Float(Default(threshold, 0.00)) # threshold arg of Y, u anv V plane AviSynth runtime functions
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.0 -> 1.0")
luma_autogain_strength = Float(Default(luma_autogain_strength, 0.5)) # luma_autogain_strength autogain strength, between 0.0 and 1.0
Assert(luma_autogain_strength>=0.0 && luma_autogain_strength <= 1.0,"RGBAdapt_auto_awb: luma_autogain_strength 0.0 -> 1.0")
gain_strength = Float(Default(gain_strength, 0.5)) # linear gain and cont curve use strength, between 0.0 and 1.0,
Assert(gain_strength>=0.0 && gain_strength <= 4.0,"RGBAdapt_auto_awb: gain_strength 0.0 -> 3.0")
cont_tune = Float(Default(cont_tune, 0.5)) # cont curve use tune, between -1.0 and 1.0,
Assert(cont_tune>=-4.0 && cont_tune <= 4.0,"RGBAdapt_auto_awb: cont_tune -3.0 -> 3.0")
bias_strength = Float(Default(bias_strength, 0.5)) # bias curves correction strength
Assert(bias_strength>=0.0 && bias_strength <= 1.0,"RGBAdapt_auto_awb: bias_strength 0.0 -> 1.0")
ScriptClip(clip, """
clip = last
#------------ Color matrix input
Kr = (matrix == "Rec601") ? 0.299 : 0.2126
Kg = (matrix == "Rec601") ? 0.587 : 0.7152
Kb = (matrix == "Rec601") ? 0.114 : 0.0722
#------------ YUV values extraction
(!isYV12(clip)) ? ConvertToYV12(clip, matrix=matrix) : clip
y = Averageluma()
u = AverageChromaU()
v = AverageChromaV()
y_max = YPlaneMax(threshold = threshold)
y_max = min (y_max, 235.0)
y_min = YPlaneMin(threshold = threshold)
y_min = max (16.0, y_min)
#----------- Automatic Y gain corrections calcul
#----------- Y autogain calcul
range_min_max = y_max - y_min
range_min_max = Max (range_min_max, 1.0)
f = float(219.0/range_min_max)
f = 1.0 + (f-1.0)*luma_autogain_strength
f = Min (3.1, Max (f, 0.0)) # to avoid below error message :
# Avisynth: access violation at 0x000496FD in C:\Windows\system32\Kernel32.dll,
# attempting to write to 0x595E308D
#----------- Y offset calcul
new_y_min = y_min * f
dy = (y_min - new_y_min)*luma_autogain_strength
#---------- 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) # Autogain offset luma is include here
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)
#---------- First pass : process with gamma curves
#----------- RGB corrections values calcul
dr = (r_awb - r)
dg = (g_awb - g)
db = (b_awb - b)
#----------- RGB correction with Rpow curve calcul
yr = pow(gamma_strength,dr/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(gamma_strength,dg/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(gamma_strength,db/128)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul
sr = (!spow_use)? 1.0 : pow(gamma_strength,dr/256.0)
sr = Min (4.0, Max (sr, 0.1))
sg = (!spow_use)? 1.0 : pow(gamma_strength,dg/256.0)
sg = Min (4.0, Max (sg, 0.1))
sb = (!spow_use)? 1.0 : pow(gamma_strength,db/256.0)
sb = Min (4.0, Max (sb, 0.1))
#--------- Spmid calcul
r_spmid = 0.5 * sr
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = 0.5 * sg
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = 0.5 * sb
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#------- Pord calcul
r_pord = (sr < 1.0) ? true : false
g_pord = (sg < 1.0) ? true : false
b_pord = (sb < 1.0) ? true : false
(!isRGB(clip)) ? ConvertToRGB24(last, matrix=matrix) : clip
output_video = RGBAdapt( \
R_Bias = 0, R_Gain = 1.0, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = 0, G_Gain = 1.0, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = 0, B_Gain = 1.0, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#---------- Second pass : process only with gain and cont curves
#----------- RGB values extraction
black = BlankClip(output_video, pixel_type="RGB24", color=$000000)
red = ShowRed(output_video,pixel_type="RGB24")
green = ShowGreen(output_video,pixel_type="RGB24")
blue = ShowBlue(output_video,pixel_type="RGB24")
red = RGBDifference(red, black)
green = RGBDifference(green, black)
blue = RGBDifference(blue, black)
#----------- RGB corrections calcul
dr_gain = r_awb - red
dg_gain = g_awb - green
db_gain = b_awb - blue
#---------- Gain calcul, autogain offset luma is include here
r_gain = f + gain_strength*dr_gain/r
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = f + gain_strength*dg_gain/g
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = f + gain_strength*db_gain/b
b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = 1.0 + dr_gain*cont_tune/r
r_cont = Min (8.0, Max (r_cont, -8.0))
g_cont = 1.0 + dg_gain*cont_tune/g
g_cont = Min (8.0, Max (g_cont, -8.0))
b_cont = 1.0 + db_gain*cont_tune/b
b_cont = Min (8.0, Max (b_cont, -8.0))
output_video = RGBAdapt( \
R_Bias = dy, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = dy, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = dy, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#---------- Third pass : process with bias curve
#----------- RGB values extraction
red = ShowRed(output_video,pixel_type="RGB24")
green = ShowGreen(output_video,pixel_type="RGB24")
blue = ShowBlue(output_video,pixel_type="RGB24")
red = RGBDifference(red, black)
green = RGBDifference(green, black)
blue = RGBDifference(blue, black)
#----------- RGB corrections calcul
dr_bias = (r_awb - red)*bias_strength
dg_bias = (g_awb - green) *bias_strength
db_bias = (b_awb - blue)*bias_strength
output_video = RGBAdapt( \
R_Bias = dr_bias+dy, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = dg_bias+dy, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = db_bias+dy, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#--------- Final output RGB values extraction for display
red = ShowRed(output_video,pixel_type="RGB24")
green = ShowGreen(output_video,pixel_type="RGB24")
blue = ShowBlue(output_video,pixel_type="RGB24")
red_out = RGBDifference(red, black)
green_out = RGBDifference(green, black)
blue_out = RGBDifference(blue, black)
output_video = (!isRGB(clip)) ? ConvertToYV12(output_video, matrix=matrix) : output_video
#-------- displayed info or no
(!show_info)? output_video : output_video\
.Subtitle("Y value : "+String(Y)+" Y autogain : "+String(f),y=40)\
.Subtitle("Red value : "+String(r)+" Target Red awb value : "+String(r_awb)+\
"\nRed Values Diff : "+String(dr)+\
"\nRpow : "+String(yr)+" Spow : "+String(sr)+" Spmid : "+String(r_spmid)+" Pord : "+String(r_pord)+\
"\nGain : "+String(r_gain)+" Cont : "+String(r_cont)+\
"\nBias correction : "+String(dr_bias)+\
"\nOutput Red value : "+String(red_out),y=70,lsp=20)\
.Subtitle("Green value : "+String(g)+" Target Green awb value : "+String(g_awb)+\
"\nGreen Values Diff : "+String(dg)+\
"\nRpow : "+String(yg)+" Spow : "+String(sg)+" Spmid : "+String(g_spmid)+" Pord : "+String(g_pord)+\
"\nGain : "+String(g_gain)+" Cont : "+String(g_cont)+\
"\nBias correction : "+String(dg_bias)+\
"\nOutput Green value : "+String(green_out),y=210,lsp=20)\
.Subtitle("Blue value : "+String(b)+" Target Blue awb value : "+String(b_awb)+\
"\nBlue Values Diff : "+String(db)+\
"\nRpow : "+String(yb)+" Spow : "+String(sb)+" Spmid : "+String(b_spmid)+" Pord : "+String(b_pord)+\
"\nGain : "+String(b_gain)+" Cont : "+String(b_cont)+\
"\nBias correction : "+String(db_bias)+\
"\nOutput Blue value : "+String(blue_out), y=350,lsp=20)
""", args = "show_info, matrix, threshold, luma_autogain_strength, gain_strength, cont_tune, gamma_strength, spow_use, bias_strength")
}
Bernardd
10th August 2015, 22:19
Hello StainlessS
I use RT_Stats now in my script. The result is better than before.
Thanks for yours nice plugins.
function RGBAdapt_auto_awb_process(clip clip, bool "show_info", string "matrix", int "x", int "y", int "w", int "h",\
float "threshold", float "autogain_strength",\
float "gamma_strength", bool "spow_use",float "gain_strength", float "cont_tune",\
float "bias_strength")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1584313#post1584313 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
show_info = Default(show_info, false) # show info or not, default false
matrix = string(Default(matrix, "Rec601") ) # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
x = int(Default(x,0)) #coords specify the source rectangle under scrutiny and are specified as for Crop(), the default 0,0,0,0 is full frame
y = int(Default(y,0)) #coords specify the source rectangle under scrutiny and are specified as for Crop(), the default 0,0,0,0 is full frame
w = int(Default(w,0)) #coords specify the source rectangle under scrutiny and are specified as for Crop(), the default 0,0,0,0 is full frame
h = int(Default(h,0)) #coords specify the source rectangle under scrutiny and are specified as for Crop(), the default 0,0,0,0 is full frame
threshold = Float(Default(threshold, 0.00)) # threshold arg of Y, u anv V plane AviSynth runtime functions
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.0 -> 1.0")
autogain_strength = Float(Default(autogain_strength, 1.0)) # autogain_strength autogain strength, between 0.0 and 1.0
Assert(autogain_strength>=0.0 && autogain_strength <= 1.0,"RGBAdapt_auto_awb: autogain_strength 0.0 -> 1.0")
gamma_strength = Float(Default(gamma_strength, 4.0)) # linear curve use strength, between 1.0 and 4.0,
Assert(gamma_strength>=1.0 && gamma_strength <= 4.0,"RGBAdapt_auto_awb: gamma_strength 1.0 -> 4.0")
spow_use = Default(spow_use, true) # enable spow curve use
gain_strength = Float(Default(gain_strength, 1.0)) # linear gain and cont curve use strength, between 0.0 and 1.0,
Assert(gain_strength>=0.0 && gain_strength <= 3.0,"RGBAdapt_auto_awb: gain_strength 0.0 -> 3.0")
cont_tune = Float(Default(cont_tune, 1.0)) # cont curve use tune, between -1.0 and 1.0,
Assert(cont_tune>=-3.0 && cont_tune <= 3.0,"RGBAdapt_auto_awb: cont_tune -3.0 -> 3.0")
bias_strength = Float(Default(bias_strength, 1.0)) # bias curves correction strength
Assert(bias_strength>=0.0 && bias_strength <= 1.0,"RGBAdapt_auto_awb: bias_strength 0.0 -> 1.0")
ScriptClip(clip, """
clip = last
#------------ Color matrix input
Kr = (matrix == "Rec601") ? 0.299 : 0.2126
Kg = (matrix == "Rec601") ? 0.587 : 0.7152
Kb = (matrix == "Rec601") ? 0.114 : 0.0722
#----------- RGV values
(!isRGB(clip)) ? ConvertToRGB24(last, matrix=matrix) : clip
r = RT_RGBChanAVe( x = x, y = y, w = w, h = h, chan = 0)
g = RT_RGBChanAVe( x = x, y = y, w = w, h = h, chan = 1)
b = RT_RGBChanAVe( x = x, y = y, w = w, h = h, chan = 2)
r_min_max_diff = RT_RgbChanMinMaxDifference( x = x, y = y, w = w, h = h, threshold = threshold, chan = 0)
g_min_max_diff = RT_RgbChanMinMaxDifference( x = x, y = y, w = w, h = h, threshold = threshold, chan = 1)
b_min_max_diff = RT_RgbChanMinMaxDifference( x = x, y = y, w = w, h = h, threshold = threshold, chan = 2)
r_min = RT_RgbChanMin( x = x, y = y, w = w, h = h, threshold = threshold, chan = 0)
g_min = RT_RgbChanMin( x = x, y = y, w = w, h = h, threshold = threshold, chan = 1)
b_min = RT_RgbChanMin( x = x, y = y, w = w, h = h, threshold = threshold, chan = 2)
#---------- First pass : process with gain curves for autogain
#--------- Autogain calcul
r_min_max_diff = Max (r_min_max_diff, 1.0)
f_red = float(255.0/r_min_max_diff)
f_red = 1.0 + (f_red-1.0)*autogain_strength
f_red = Min (8.0, Max (f_red, -8.0))
new_r_min = r_min * f_red
dred = (r_min - new_r_min)*autogain_strength
dred = Min (512.0, Max (dred, -512.0))
g_min_max_diff = Max (g_min_max_diff, 1.0)
f_green = float(255.0/g_min_max_diff)
f_green = 1.0 + (f_green-1.0)*autogain_strength
f_green = Min (8.0, Max (f_green, -8.0))
new_g_min = g_min * f_green
dgreen = (g_min - new_g_min)*autogain_strength
dgreen = Min (512.0, Max (dgreen, -512.0))
f_blue = float(255.0/b_min_max_diff)
f_blue = 1.0 + (f_blue-1.0)*autogain_strength
f_blue = Min (8.0, Max (f_blue, -8.0))
new_b_min = b_min * f_blue
dblue = (b_min - new_b_min)*autogain_strength
dblue = Min (512.0, Max (dblue, -512.0))
output_video = RGBAdapt( \
R_Bias = dred, R_Gain = f_red, R_Cont = 1.0, R_RPow = 1.0, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false,\
G_Bias = dgreen, G_Gain = f_green, G_Cont = 1.0, G_RPow = 1.0, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = dblue, B_Gain = f_blue, B_Cont = 1.0, B_RPow = 1.0, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
#---------- Second pass : process with gamma curves
#----------- RGB values extraction
red = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 0)
green = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 1)
blue = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 2)
y_autogain = kr*red + kg*green + kb*blue
#----------- RGB corrections values calcul
dr = (y_autogain - red)
dg = (y_autogain - green)
db = (y_autogain - blue)
#----------- RGB correction with Rpow curve calcul
yr = pow(gamma_strength,dr/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(gamma_strength,dg/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(gamma_strength,db/128)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul
sr = (!spow_use)? 1.0 : pow(gamma_strength,dr/256.0)
sr = Min (4.0, Max (sr, 0.1))
sg = (!spow_use)? 1.0 : pow(gamma_strength,dg/256.0)
sg = Min (4.0, Max (sg, 0.1))
sb = (!spow_use)? 1.0 : pow(gamma_strength,db/256.0)
sb = Min (4.0, Max (sb, 0.1))
#--------- Spmid calcul
r_spmid = 0.5 * sr
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = 0.5 * sg
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = 0.5 * sb
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#------- Pord calcul
r_pord = (sr < 1.0) ? true : false
g_pord = (sg < 1.0) ? true : false
b_pord = (sb < 1.0) ? true : false
output_video = RGBAdapt( \
R_Bias = dred, R_Gain = f_red, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = dgreen, G_Gain = f_green, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = dblue, B_Gain = f_blue, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#---------- Third pass : process only with gain and cont curves
#----------- RGB values extraction
red = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 0)
green = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 1)
blue = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 2)
#----------- RGB corrections calcul
dr_gain = (y_autogain - red) # with y_autogain correction is more sensitive than with luma of output video
dg_gain = (y_autogain - green)
db_gain = (y_autogain - blue)
#---------- Gain calcul, autogain offset luma is include here
r_gain = f_red + gain_strength*dr_gain/r
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = f_green + gain_strength*dg_gain/g
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = f_blue + gain_strength*db_gain/b
b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = 1.0 + dr_gain*cont_tune/r
r_cont = Min (8.0, Max (r_cont, -8.0))
g_cont = 1.0 + dg_gain*cont_tune/g
g_cont = Min (8.0, Max (g_cont, -8.0))
b_cont = 1.0 + db_gain*cont_tune/b
b_cont = Min (8.0, Max (b_cont, -8.0))
output_video = RGBAdapt( \
R_Bias = dred, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = dgreen, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = dblue, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#---------- Fourth pass : process with bias curve
#----------- RGB values extraction
red = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 0)
green = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 1)
blue = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 2)
#----------- RGB corrections calcul
dr_bias = (y_autogain - red)*bias_strength # with y_autogain correction is more sensitive than with luma of output video
dg_bias = (y_autogain - green) *bias_strength
db_bias = (y_autogain - blue)*bias_strength
rb = dr_bias + dred
rb = Min (512.0, Max (rb, -512.0))
gb = dg_bias + dgreen
gb = Min (512.0, Max (gb, -512.0))
bb = db_bias + dblue
bb = Min (512.0, Max (bb, -512.0))
output_video = RGBAdapt( \
R_Bias = rb, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = gb, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = bb, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#--------- Final output RGB values extraction for display
red_out = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 0)
green_out = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 1)
blue_out = RT_RGBChanAVe(output_video, x = x, y = y, w = w, h = h, chan = 2)
output_video = (!isRGB(clip)) ? ConvertToYV12(output_video, matrix=matrix) : output_video
#-------- displayed info or no
(!show_info)? output_video : output_video\
.Subtitle("Red value : "+String(r)+\
"\nRed Values Diff : "+String(dr)+\
"\nRpow : "+String(yr)+" Spow : "+String(sr)+" Spmid : "+String(r_spmid)+" Pord : "+String(r_pord)+\
"\nRed autogain : "+String(f_red)+ " Gain : "+String(r_gain)+" Cont : "+String(r_cont)+\
"\nBias correction : "+String(dr_bias)+\
"\nOutput Red value : "+String(red_out)+" "+String(f_red),y=70,lsp=20)\
.Subtitle("Green value : "+String(g)+\
"\nGreen Values Diff : "+String(dg)+\
"\nRpow : "+String(yg)+" Spow : "+String(sg)+" Spmid : "+String(g_spmid)+" Pord : "+String(g_pord)+\
"\nGreen autogain : "+String(f_green)+ " Gain : "+String(g_gain)+" Cont : "+String(g_cont)+\
"\nBias correction : "+String(dg_bias)+\
"\nOutput Green value : "+String(green_out)+" "+String(f_green),y=210,lsp=20)\
.Subtitle("Blue value : "+String(b)+\
"\nBlue Values Diff : "+String(db)+\
"\nRpow : "+String(yb)+" Spow : "+String(sb)+" Spmid : "+String(b_spmid)+" Pord : "+String(b_pord)+\
"\nBlue autogain : "+String(f_blue)+ " Gain : "+String(b_gain)+" Cont : "+String(b_cont)+\
"\nBias correction : "+String(db_bias)+\
"\nOutput Blue value : "+String(blue_out)+" "+String(f_blue), y=350,lsp=20)
""", args = "show_info, matrix, x, y, w , h," +\
"threshold, autogain_strength, gain_strength, cont_tune, gamma_strength, spow_use, bias_strength")
}
StainlessS
10th August 2015, 22:44
Hi there, you are a busy little 'B' :)
Early in your script you call RT_RGBChanAVe, RT_RgbChanMinMaxDifference, and RT_RgbChanMin for all three R,G,B channels, 9 function calls.
Can use RT_RgbChanStats() to simultaneously get all 9.
********************************************
********* RGB MASKED Channel FUNCTIONS *****
********************************************
RGB32, RGB24 source clip.
The source clip c must be RGB32 or RGB24.
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.
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)
EDIT: above should be, clip "mask"=NOT_USED' ie Undefined.
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")
""")
Use chan arg -1 (all three channels) and flags (1+4+16) = 21, also need to set Threshold.
0 1($01) RT_RgbChanMin() "Min" (0->255)
2 4($04) RT_RgbChanMinMaxDifference() "MinMaxDiff" (0->255)
4 16($10) RT_RgbChanAve() "Ave" (0.0->255.0)
EDIT: I've just noticed an error in above doc, says 'int "Mask"=NOT_USED', should be 'clip "Mask"=NOT_USED'.
Bernardd
11th August 2015, 11:41
Thanks StainlessS
I am studying your advice.
Bernardd
5th September 2015, 21:13
Hello StainlessS,
To get a good white balance, it is necessary to find the good value for gain. Thus now my script have three ways to adjust gain value.
First way, tune autogain by color channel.
Second way, tune channel standard deviation gain.
An last, tune channel gain in accordance with gray world theory.
I have not found a process to get a automatic good adjust with each video, but i think that default values can be enough for many videos and
i believe we can find a args tunning combination to get a likeable result.
In accordance with your advice, i have written the RT_Stats calls.
The script is in follow post (pb of characters nb)
Bernardd
5th September 2015, 21:17
Below the new script, part 1
function RGBAdapt_auto_awb_process(clip clip, bool "show_info", string "matrix", int "x", int "y", int "w", int "h",\
float "threshold", float "autogain_strength", float "std_deviation_gain_strength",\
float "gamma_strength", bool "spow_use",float "gain_strength", float "cont_tune",\
float "bias_strength")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1584313#post1584313 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
show_info = Default(show_info, false) # show info or not, default false
matrix = string(Default(matrix, "Rec601") ) # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
x = int(Default(x,0)) #coords specify the source rectangle under scrutiny and are specified as for Crop(), the default 0,0,0,0 is full frame
y = int(Default(y,0)) #coords specify the source rectangle under scrutiny and are specified as for Crop(), the default 0,0,0,0 is full frame
w = int(Default(w,0)) #coords specify the source rectangle under scrutiny and are specified as for Crop(), the default 0,0,0,0 is full frame
h = int(Default(h,0)) #coords specify the source rectangle under scrutiny and are specified as for Crop(), the default 0,0,0,0 is full frame
threshold = Float(Default(threshold, 0.00)) # threshold arg of Y, u anv V plane AviSynth runtime functions
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.0 -> 1.0")
autogain_strength = Float(Default(autogain_strength, 1.0)) # autogain_strength autogain strength, between 0.0 and 1.0
Assert(autogain_strength>=0.0 && autogain_strength <= 1.0,"RGBAdapt_auto_awb: autogain_strength 0.0 -> 1.0")
std_deviation_gain_strength = Float(Default(std_deviation_gain_strength, 1.0)) # std_deviation_gain_strength, between 0.0 and 1.0
Assert(autogain_strength>=0.0 && autogain_strength <= 1.0,"RGBAdapt_auto_awb: autogain_strength 0.0 -> 1.0")
gamma_strength = Float(Default(gamma_strength, 4.0)) # linear curve use strength, between 1.0 and 4.0,
Assert(gamma_strength>=1.0 && gamma_strength <= 4.0,"RGBAdapt_auto_awb: gamma_strength 1.0 -> 4.0")
spow_use = Default(spow_use, true) # enable spow curve use
gain_strength = Float(Default(gain_strength, 1.0)) # gain curve use strength, between 0.0 and 2.0,
Assert(gain_strength>=0.0 && gain_strength <= 2.0,"RGBAdapt_auto_awb: gain_strength 0.0 -> 2.0")
cont_tune = Float(Default(cont_tune, 0.5)) # cont curve use tune, between -2.0 and 2.0,
Assert(cont_tune>=-2.0 && cont_tune <= 2.0,"RGBAdapt_auto_awb: cont_tune -2.0 -> 2.0")
bias_strength = Float(Default(bias_strength, 1.0)) # bias curves correction strength
Assert(bias_strength>=0.0 && bias_strength <= 2.0,"RGBAdapt_auto_awb: bias_strength 0.0 -> 2.0")
Bernardd
5th September 2015, 21:19
Below the new script, part 2 (to paste after part 1 end). This part has been update the 7 september (try version lines were deleted).
ScriptClip(clip, """
clip = last
(!isRGB(clip)) ? ConvertToRGB24(last, matrix=matrix) : clip
#---------- First pass : gain curves process for each channel autogain
RT_RgbChanStats( x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4)
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) # to avoid division by 0
RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01)
RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
RCS_Max_0 = Max (RCS_Max_0, 0.01) # to avoid division by 0
RCS_Max_1 = Max (RCS_Max_1, 0.01)
RCS_Max_2 = Max (RCS_Max_2, 0.01)
#--------- Autogain calcul
red_autogain_factor = float(255.0/RCS_MinMaxDiff_0)
new_r_max = RCS_Max_0 * red_autogain_factor
red_autogain_ponderation = 255.0/new_r_max # need for videos with very week contrast
red_autogain_factor = 1.0 + (red_autogain_factor-1.0) * autogain_strength * red_autogain_ponderation
new_r_min = RCS_Min_0 * red_autogain_factor # bias correction to keep the lower start value
red_autogain_bias = (RCS_Min_0 - new_r_min)
green_autogain_factor = float(255.0/RCS_MinMaxDiff_1)
new_g_max = RCS_Max_1 * green_autogain_factor
green_autogain_ponderation = 255.0/new_g_max
green_autogain_factor = 1.0 + (green_autogain_factor-1.0) * autogain_strength * green_autogain_ponderation
new_g_min = RCS_Min_1 * green_autogain_factor # bias correction to keep the lower start value
green_autogain_bias = (RCS_Min_1 - new_g_min)
blue_autogain_factor = float(255.0/RCS_MinMaxDiff_2)
new_b_max = RCS_Max_2 * blue_autogain_factor
blue_autogain_ponderation = 255.0/new_b_max
blue_autogain_factor = 1.0 + (blue_autogain_factor-1.0) * autogain_strength * blue_autogain_ponderation
new_b_min = RCS_Min_2 * green_autogain_factor # bias correction to keep the lower start value
blue_autogain_bias = (RCS_Min_2 - new_b_min)
r_bias = red_autogain_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = green_autogain_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = blue_autogain_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
r_gain = red_autogain_factor
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = green_autogain_factor
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = blue_autogain_factor
b_gain = Min (8.0, Max (b_gain, -8.0))
output_video = RGBAdapt( \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = 1.0, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = 1.0, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = 1.0, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
#---------- Second pass : gain curves process with standard deviation use
RT_RgbChanStats(output_video, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+32)
RCS_Stdev_0 = Max (RCS_Stdev_0, 0.01) # to avoid division by 0
RCS_Stdev_1 = Max (RCS_Stdev_1, 0.01)
RCS_Stdev_2 = Max (RCS_Stdev_2, 0.01)
red_std_deviation_factor = (RCS_Stdev_0 + RCS_Stdev_1 + RCS_Stdev_2)/(3 * RCS_Stdev_0)
red_std_deviation_factor = 1 + (red_std_deviation_factor -1.0) * std_deviation_gain_strength
new_sr_min = RCS_Min_0 * red_std_deviation_factor
red_std_deviation_bias = (RCS_Min_0 - new_sr_min)
green_std_deviation_factor = (RCS_Stdev_0 + RCS_Stdev_1 + RCS_Stdev_2)/(3 * RCS_Stdev_1)
green_std_deviation_factor = 1 + (green_std_deviation_factor -1.0) * std_deviation_gain_strength
new_sg_min = RCS_Min_1 * green_std_deviation_factor
green_std_deviation_bias = (RCS_Min_1 - new_sg_min)
blue_std_deviation_factor = (RCS_Stdev_0 + RCS_Stdev_1 + RCS_Stdev_2)/(3 * RCS_Stdev_2)
blue_std_deviation_factor = 1 + (blue_std_deviation_factor -1.0) * std_deviation_gain_strength
new_sb_min = RCS_Min_2 * blue_std_deviation_factor
blue_std_deviation_bias = (RCS_Min_2 - new_sb_min)
r_bias = r_bias + red_std_deviation_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = g_bias + green_std_deviation_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = b_bias + blue_std_deviation_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
r_gain = r_gain * red_std_deviation_factor
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = g_gain * green_std_deviation_factor
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = b_gain * blue_std_deviation_factor
b_gain = Min (8.0, Max (b_gain, -8.0))
output_video = RGBAdapt( \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = 1.0, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = 1.0, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = 1.0, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
#---------- Third pass : gamma curves process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(output_video, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
#----------- RGB corrections values calcul
dr = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_0)
dg = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_1)
db = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_2)
#----------- RGB correction with Rpow curve calcul
yr = pow(gamma_strength,dr/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(gamma_strength,dg/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(gamma_strength,db/128)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul
sr = (!spow_use)? 1.0 : pow(gamma_strength,dr/256.0)
sr = Min (4.0, Max (sr, 0.1))
sg = (!spow_use)? 1.0 : pow(gamma_strength,dg/256.0)
sg = Min (4.0, Max (sg, 0.1))
sb = (!spow_use)? 1.0 : pow(gamma_strength,db/256.0)
sb = Min (4.0, Max (sb, 0.1))
#--------- Spmid calcul
r_spmid = 0.5 * sr
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = 0.5 * sg
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = 0.5 * sb
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#------- Pord calcul
r_pord = (sr < 1.0) ? true : false
g_pord = (sg < 1.0) ? true : false
b_pord = (sb < 1.0) ? true : false
output_video = RGBAdapt( \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#---------- Fourth pass : gain and cont curves process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(output_video, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
#----------- RGB corrections calcul
dr_gain = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_0)
dg_gain = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_1)
db_gain = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_2)
#---------- Gain calcul
red_gain_factor = 1.0 + dr_gain/RCS_Ave_0 * gain_strength
green_gain_factor = 1.0 + dg_gain/RCS_Ave_1 * gain_strength
blue_gain_factor = 1.0 + db_gain/RCS_Ave_2 * gain_strength
r_gain = red_autogain_factor * red_std_deviation_factor * red_gain_factor
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = green_autogain_factor * green_std_deviation_factor * green_gain_factor
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = blue_autogain_factor * blue_std_deviation_factor * blue_gain_factor
b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = 1.0 + dr_gain/RCS_Ave_0 * RCS_Ave_1/RCS_Ave_0 * cont_tune
r_cont = Min (8.0, Max (r_cont, -8.0))
g_cont = 1.0 + dg_gain/RCS_Ave_1 * cont_tune
g_cont = Min (8.0, Max (g_cont, -8.0))
b_cont = 1.0 + db_gain/RCS_Ave_2 * RCS_Ave_1/RCS_Ave_2 * cont_tune
b_cont = Min (8.0, Max (b_cont, -8.0))
output_video = RGBAdapt( \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#---------- Last pass : bias curve process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(output_video, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
#----------- RGB corrections calcul
dr_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_0) * bias_strength
dg_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_1) * bias_strength
db_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_2) * bias_strength
r_bias = red_autogain_bias + red_std_deviation_bias + dr_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = green_autogain_bias + green_std_deviation_bias + dg_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = blue_autogain_bias + blue_std_deviation_bias + db_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
output_video = RGBAdapt( \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#--------- Final RGB values extraction for display
RT_RgbChanStats(output_video, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
red_out = RCS_Ave_0
green_out = RCS_Ave_1
blue_out = RCS_Ave_2
RT_RgbChanStats( x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
output_video = (!isRGB(clip)) ? ConvertToYV12(output_video, matrix=matrix) : output_video
#-------- displayed info or no
(!show_info)? output_video : output_video\
.Subtitle("Red value : "+String(RCS_Ave_0)+\
"\nAutogain : "+String(red_autogain_factor)+ " Standard deviation gain : "+String(red_std_deviation_factor) +\
" Gray world gain : " + String(red_gain_factor)+\
"\nRpow : "+String(yr)+" Spow : "+String(sr)+" Spmid : "+String(r_spmid)+" Pord : "+String(r_pord)+\
"\nTotal gain : "+String(r_gain)+" Gray world Cont : "+String(r_cont)+\
"\nBias : "+String(dr_bias)+\
"\nOutput Red value : "+String(red_out)+" ",y=60,lsp=20)\
.Subtitle("Green value : "+String(RCS_Ave_1)+\
"\nAutogain : "+String(green_autogain_factor)+ " Standard deviation gain : "+String(green_std_deviation_factor)+\
" Gray world gain : " + String(green_gain_factor)+\
"\nRpow : "+String(yg)+" Spow : "+String(sg)+" Spmid : "+String(g_spmid)+" Pord : "+String(g_pord)+\
"\nTotal gain : "+String(g_gain)+" Gray world Cont : "+String(g_cont)+\
"\nBias correction : "+String(dg_bias)+\
"\nOutput Green value : "+String(green_out)+" ",y=210,lsp=20)\
.Subtitle("Blue value : "+String(RCS_Ave_2)+\
"\nAutogain : "+String(blue_autogain_factor)+ " Std deviation gain : "+String(blue_std_deviation_factor) +\
" Gray world gain : " + String(blue_gain_factor)+\
"\nRpow : "+String(yb)+" Spow : "+String(sb)+" Spmid : "+String(b_spmid)+" Pord : "+String(b_pord)+\
"\nTotal gain : "+String(b_gain)+" Gray world Cont : "+String(b_cont)+\
"\nBias : "+String(db_bias)+\
"\nOutput Blue value : "+String(blue_out)+" ", y=360,lsp=20)
""", args = "show_info, matrix, x, y, w , h," +\
"threshold, autogain_strength, std_deviation_gain_strength, gamma_strength, spow_use, gain_strength, cont_tune,"+\
"bias_strength")
}
Bernardd
24th September 2015, 14:16
Hello StainlessS
I tried to automate the white balance using your plugin RGBAdapt. So I wrote a RGBAdapt_AWB_process script function, which allows the use of different RGB values of the picture. The script compute the autogain for each color channel, a white balance based on the standard deviation and white balance according to the theory of gray world. At each level, I introduced a weighting factor to manual adjust of automatism.
The script usually gives acceptable results with default settings, but it requires regular manual adjustment. I have not found the formula linking the manuals factors, which give the right result. The difficulty is that each image is a special case.
Another difficulty, action manuals factors is sensitive, we must act with two decimal places.
Final difficulty, extraction of RGB picture values is based on the scrutinized area (of course). The result of automatic white balance is related to this scrutinized area.
We can define with RT STATS the examined area, but I do not see how to automate this definition. Manual intervention is therefore necessary.
My script do not thus perform an automatic white balance, it is simply an help to search for balance. It allows manual adjustments described above, but it remains difficult to use with command line.
A GUI is required. My programming language skills are limited, I have done that interface using the features "User Sliders" and "Tag selection for toggling" of AvspMod. I know you do not use AvspMod, but you may be tempted by a try.
The script includes the definition of user sliders and insertion of three selection tags. The bottom tag to show or not to show the comparison screen of different versions of the video. the two top tag to select the suitable display of adjustment user sliders for the trial version. I have noticed that by reducing all args with the same adjustment factor, I often approached an acceptable result. To speed adjustments, one can choose linked parameters mode. In linked mode, reducing the examined area is symmetrical, factors of corrections weighting are equal. In no linked mode : all parameters can be adjusted independently.
Below one picture to show default setting result :
link DropBox
https://www.dropbox.com/s/cpgsxvm9uttbfw5/default%20setting%20demo.jpg?dl=0
Below one picture to show scrutinized aera setting interest :
link DropBox
https://www.dropbox.com/s/tdv1bvx22l8n2np/scrutinized%20evidence.jpg?dl=0
End the script
link DropBox
https://www.dropbox.com/s/5svf6g62ozt4vyz/RGBAdapt_awb_en.avs?dl=0
StainlessS
8th October 2015, 13:16
Hi Bernardd, can you post just the original images from previous post, thanx :)
Bernardd
8th October 2015, 16:57
Hello StainlessS,
For a quick answer without waiting for attachment approval, three links Dropbox (available 30 days)
The images are taken from a film 8 mm and S8. I added a short extract from the winter scene, because it is typical of a disturbed camera white balance by a foreign object.
The RT_Stats scrutinized args are a marvelous idea.
Thank you.
Picture one (https://www.dropbox.com/s/nv31dxr77eu1nn2/RGBAdapt_awb_fr000088.bmp?dl=0)
Picture two (https://www.dropbox.com/s/4224xtusj4f40kz/RGBAdapt_awb_fr003389.bmp?dl=0)
https://www.dropbox.com/s/8cscqk1udshu7dk/extrait.avi?dl=0
StainlessS
8th October 2015, 21:13
Bernardd, got them thanx :)
Bernardd
30th July 2016, 16:20
Hello StainlessS,
I have written my script.
Now, it is more automatic. I have replaced strenght args by ponderation quotient formulas ( formulas are not scientific but result of test)
Now, only three args :
- under scrutiny aera coords
- threshold of MinMaxDiff values extraction
- and spow to enable or not the spow process (experimental, not scientific)
When one year ago , on french forum http://letransfert.soforums.com/t936...s-couleurs.htm, we have discussed about color correction,
Dani has demonstrated that the first and important challenge is to tune gain.
With GamMac you have found this problem. Named autogain or scale it is for me the same fight.
In my script, when i modify gain i must modify bias in accordance.
With some frame where the channels values minimum are not nul, and the gain big, i get dark picture.
After many test, i found the idea to decrease gain for this frame with use formulas 255.0/channel mac value. I use this limited gain only for bias calculation.
I hope this can give you some idea for GamMac
Bernard
function RGBAdapt_auto_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
float "threshold", bool "spow")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1584313#post1584313 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
Assert(IsYV12(clip) || IsRGB(clip)," Input video colorspace must be YV12 or RGB, not YUV")
matrix = string(Default(matrix, "Rec601") ) # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
show_scrutinized = Default(show_scrutinized, false) # show scrutinized aera or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.00)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(x>=0.00 && x <= 0.99,"RGBAdapt_auto_awb: x 0.00 -> 0.99")
y = float(Default(y,0.00)) #heignt percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(y>=0.00 && y <= 0.99,"RGBAdapt_auto_awb: y 0.00 -> 0.99")
w = float(Default(w,0.00)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(w>=0.00 && w <= 0.99,"RGBAdapt_auto_awb: w 0.00 -> 0.99")
Assert(x+w>=0.00 && x+w <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
h = float(Default(h,0.00)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(h>=0.00 && h <= 0.99,"RGBAdapt_auto_awb: h 0.00 -> 0.99")
Assert(y+h>=0.00 && y+h <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
threshold = Float(Default(threshold, 0.00)) # threshold arg of y, u anv v plane AviSynth runtime functions
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.00 -> 1.00")
spow = Default(spow, false) # enable Spow process or not, default false
ScriptClip(clip, """
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#---------- Convert to RGB color space
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#---------- First pass : autogain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
#----- extraction for final display
r_Min = RCS_Min_0 g_min = RCS_Min_1 b_min = RCS_Min_2
r_Max = RCS_Max_0 g_max = RCS_Max_1 b_max = RCS_Max_2
r_MinmaxDiff = RCS_MinMaxDiff_0 g_minMaxDiff = RCS_MinMaxDiff_1 b_MinMaxDiff = RCS_max_2
r_Med = RCS_Med_0 g_Med = RCS_Med_1 b_Med = RCS_Med_2
r_Ave = RCS_Ave_0 g_Ave = RCS_Ave_1 b_Ave = RCS_Ave_2
#---- autogain process
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) # to avoid division by 0
RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01)
RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
r_gain = float(255.0/RCS_MinMaxDiff_0)
r_gain = Min (8.0, Max (r_gain, -8.0))
r_gain_limited = float(255.0/RCS_Max_0)
r_gain_limited = Min (8.0, Max (r_gain_limited, -8.0))
r_bias = - RCS_Min_0 * r_gain_limited * RCS_Max_0/float(RCS_MinMaxDiff_0)
r_bias = Min (512.0, Max (r_bias, -512.0))
g_gain = float(255.0/RCS_MinMaxDiff_1)
g_gain = Min (8.0, Max (g_gain, -8.0))
g_gain_limited = float(255.0/RCS_Max_1)
g_gain_limited = Min (8.0, Max (g_gain_limited, -8.0))
g_bias = - RCS_Min_1 * g_gain_limited * RCS_Max_1/float(RCS_MinMaxDiff_1)
g_bias = Min (512.0, Max (g_bias, -512.0))
b_gain = float(255.0/RCS_MinMaxDiff_2)
b_gain = Min (8.0, Max (b_gain, -8.0))
b_gain_limited = float(255.0/RCS_Max_2)
b_gain_limited = Min (8.0, Max (b_gain_limited, -8.0))
b_bias = - RCS_Min_2 * b_gain_limited * RCS_Max_2/float(RCS_MinMaxDiff_2)
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip,\
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = 1.0, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = 1.0, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = 1.0, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
#---------- Second pass : gamma curves process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 8+16)
#----------- RGB corrections values calcul
dr = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_0)
dg = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_1)
db = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_2)
#----- RGB correction with Rpow curve calcul
yr = pow(4.0,(RCS_Ave_0/float(RCS_MinMaxDiff_0)) * dr/128) # If we replace RCS_Ave by RCS_Max, we get a more cold look
yr = Min (4.0, Max (yr, 0.1))
yg = pow(4.0,(RCS_Ave_1/float(RCS_MinMaxDiff_1)) * dg/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(4.0,(RCS_Ave_2/float(RCS_MinMaxDiff_2)) * db/128)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul ---- Experimental
sr = (Spow == true) ? pow(4.0,(RCS_Ave_0/float(RCS_MinMaxDiff_0)) * dr/256.0) : 1.0
sr = Min (4.0, Max (sr, 0.1))
sg = (Spow == true) ? pow(4.0,(RCS_Ave_1/float(RCS_MinMaxDiff_1)) * dg/256.0) : 1.0
sg = Min (4.0, Max (sg, 0.1))
sb = (Spow == true) ? pow(4.0,(RCS_Ave_2/float(RCS_MinMaxDiff_2)) * db/256.0) : 1.0
sb = Min (4.0, Max (sb, 0.1))
#--------- Spmid calcul
r_spmid = 0.5 * (float(RCS_MinMaxDiff_0/RCS_Ave_0))
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = 0.5 * (float(RCS_MinMaxDiff_1)/RCS_Ave_1)
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = 0.5 * (float(RCS_MinMaxDiff_2)/RCS_Ave_2)
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#------- Pord calcul
r_pord = (RCS_Med_0>RCS_Ave_0) ? true : false
g_pord = (RCS_Med_1>RCS_Ave_1) ? true : false
b_pord = (RCS_Med_2>RCS_Ave_2) ? true : false
RGBAdapt( RGB_clip, \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#---------- Last pass : bias curve process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 8+16)
#----------- RGB corrections calcul
dr_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_0) * RCS_Ave_0/float(RCS_MinMaxDiff_0)
dg_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_1) * RCS_Ave_1/float(RCS_MinMaxDiff_1)
db_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_2) * RCS_Ave_2/float(RCS_MinMaxDiff_2)
r_bias = r_bias + dr_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = g_bias + dg_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = b_bias + db_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip, \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#--------- Final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
(!show_info)? last : last\
.Subtitle("Red value : "+\
"\nDeparture"+\
"\nAverage :" + String(r_Ave) + " Median : " + String(r_Med) + " Min/max : " + String(r_MinMaxDiff)\
+ " Min : " + String(r_Min)+ " Max : " + String(r_Max)+\
"\n R_bias : " + String(r_bias) + " R_gain : " + String(r_gain) + " R_rpow : " + String(yr)+\
"\n R_spow : " + String(sr) + " R_spmid : " + String(r_spmid) + " R_pord : " + String(r_pord)+\
"\nFinish"+\
"\nAverage :" + String(RCS_Ave_0) + " Median : " + String(RCS_Med_0) + " Min/max : " + String(RCS_MinMaxDiff_0)\
+ " Min : " + String(RCS_Min_0)+ " Max : " + String(RCS_Max_0)\
,y=60,lsp=20)\
.Subtitle("Green value : "+\
"\nDeparture"+\
"\nAverage :" + String(g_Ave) + " Median : " + String(g_Med) + " Min/max : " + String(g_MinMaxDiff)\
+ " Min : " + String(g_Min)+ " Max : " + String(g_Max)+\
"\n G_bias : " + String(g_bias) + " G_gain : " + String(g_gain) + " G_rpow : " + String(yg)+\
"\n G_spow : " + String(sg) + " G_spmid : " + String(g_spmid) + " G_pord : " + String(g_pord)+\
"\nFinish"+\
"\nAverage :" + String(RCS_Ave_1) + " Median : " + String(RCS_Med_1) + " Min/max : " + String(RCS_MinMaxDiff_1)\
+ " Min : " + String(RCS_Min_1)+ " Max : " + String(RCS_Max_1)\
,y=210,lsp=20)\
.Subtitle("Blue value : "+\
"\nDeparture"+\
"\nAverage :" + String(b_Ave) + " Median : " + String(b_Med) + " Min/max : " + String(b_MinMaxDiff)\
+ " Min : " + String(b_Min)+ " Max : " + String(b_Max)+\
"\n B_bias : " + String(b_bias) + " B_gain : " + String(b_gain) + " B_rpow : " + String(yb)+\
"\n B_spow : " + String(sb) + " B_spmid : " + String(b_spmid) + " B_pord : " + String(b_pord)+\
"\nFinish"+\
"\nAverage :" + String(RCS_Ave_2) + " Median : " + String(RCS_Med_2) + " Min/max : " + String(RCS_MinMaxDiff_2)\
+ " Min : " + String(RCS_Min_2)+ " Max : " + String(RCS_Max_2)\
, y=360,lsp=20)
#-------- display scrutinized aera
scrutinized_green = BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
(!show_scrutinized)? last : scrutinized
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
return last """, args = "clip, matrix, show_info, show_scrutinized, x, y, w , h, threshold, spow")
}
Bernardd
1st August 2016, 10:55
Last version of script. Corrected some bug of rgb values extraction in accordance with pass. Changed default value for threshold, now 0.50.
Changed input datas for experimental spow process.
function RGBAdapt_auto_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
float "threshold", bool "spow")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1584313#post1584313 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
Assert(IsYV12(clip) || IsRGB(clip)," Input video colorspace must be YV12 or RGB, not YUV")
matrix = string(Default(matrix, "Rec601") ) # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
show_scrutinized = Default(show_scrutinized, false) # show scrutinized aera or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.00)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(x>=0.00 && x <= 0.99,"RGBAdapt_auto_awb: x 0.00 -> 0.99")
y = float(Default(y,0.00)) #heignt percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(y>=0.00 && y <= 0.99,"RGBAdapt_auto_awb: y 0.00 -> 0.99")
w = float(Default(w,0.00)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(w>=0.00 && w <= 0.99,"RGBAdapt_auto_awb: w 0.00 -> 0.99")
Assert(x+w>=0.00 && x+w <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
h = float(Default(h,0.00)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(h>=0.00 && h <= 0.99,"RGBAdapt_auto_awb: h 0.00 -> 0.99")
Assert(y+h>=0.00 && y+h <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
threshold = Float(Default(threshold, 0.50)) # threshold arg of y, u anv v plane AviSynth runtime functions
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.00 -> 1.00")
spow = Default(spow, false) # enable Spow process or not, default false
ScriptClip(clip, """
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#---------- Convert to RGB color space
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#---------- First pass : autogain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
#----- extraction for final display
r_Min = RCS_Min_0 g_min = RCS_Min_1 b_min = RCS_Min_2
r_Max = RCS_Max_0 g_max = RCS_Max_1 b_max = RCS_Max_2
r_MinmaxDiff = RCS_MinMaxDiff_0 g_minMaxDiff = RCS_MinMaxDiff_1 b_MinMaxDiff = RCS_max_2
r_Med = RCS_Med_0 g_Med = RCS_Med_1 b_Med = RCS_Med_2
r_Ave = RCS_Ave_0 g_Ave = RCS_Ave_1 b_Ave = RCS_Ave_2
#---- autogain process
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) # to avoid division by 0
RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01)
RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
r_gain = float(255.0/RCS_MinMaxDiff_0)
r_gain = Min (8.0, Max (r_gain, -8.0))
r_gain_limited = float(255.0/RCS_Max_0)
r_gain_limited = Min (8.0, Max (r_gain_limited, -8.0))
r_bias = - RCS_Min_0 * r_gain_limited * RCS_Max_0/float(RCS_MinMaxDiff_0)
r_bias = Min (512.0, Max (r_bias, -512.0))
g_gain = float(255.0/RCS_MinMaxDiff_1)
g_gain = Min (8.0, Max (g_gain, -8.0))
g_gain_limited = float(255.0/RCS_Max_1)
g_gain_limited = Min (8.0, Max (g_gain_limited, -8.0))
g_bias = - RCS_Min_1 * g_gain_limited * RCS_Max_1/float(RCS_MinMaxDiff_1)
g_bias = Min (512.0, Max (g_bias, -512.0))
b_gain = float(255.0/RCS_MinMaxDiff_2)
b_gain = Min (8.0, Max (b_gain, -8.0))
b_gain_limited = float(255.0/RCS_Max_2)
b_gain_limited = Min (8.0, Max (b_gain_limited, -8.0))
b_bias = - RCS_Min_2 * b_gain_limited * RCS_Max_2/float(RCS_MinMaxDiff_2)
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip,\
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = 1.0, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = 1.0, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = 1.0, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
#---------- Second pass : gamma curves process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 4+16)
#----------- RGB corrections values calcul
dr = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_0)
dg = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_1)
db = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_2)
#----- RGB correction with Rpow curve calcul
yr = pow(4.0,(RCS_Ave_0/float(RCS_MinMaxDiff_0)) * dr/128)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(4.0,(RCS_Ave_1/float(RCS_MinMaxDiff_1)) * dg/128)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(4.0,(RCS_Ave_2/float(RCS_MinMaxDiff_2)) * db/128)
yb = Min (4.0, Max (yb, 0.1))
RGBAdapt( RGB_clip, \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = yr, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = yg, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = yb, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
#---------- Third pass : spow curves process experimental based on channel average and median difference value
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 8+16)
#----------- RGB correction with Spow curve calcul ---- Experimental
sr = (Spow == true) ? pow(4.0,(RCS_Med_0/float(RCS_Ave_0)) * dr/256.0) : 1.0
sr = Min (4.0, Max (sr, 0.1))
sg = (Spow == true) ? pow(4.0,(RCS_Med_1/float(RCS_Ave_1)) * dg/256.0) : 1.0
sg = Min (4.0, Max (sg, 0.1))
sb = (Spow == true) ? pow(4.0,(RCS_Med_2/float(RCS_Ave_2)) * db/256.0) : 1.0
#--------- Spmid calcul
r_spmid = 0.5 * (float(RCS_Med_0/RCS_Ave_0))
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = 0.5 * (float(RCS_Med_1)/RCS_Ave_1)
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = 0.5 * (float(RCS_Med_2)/RCS_Ave_2)
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#------- Pord calcul
r_pord = (RCS_Med_0>RCS_Ave_0) ? true : false
g_pord = (RCS_Med_1>RCS_Ave_1) ? true : false
b_pord = (RCS_Med_2>RCS_Ave_2) ? true : false
RGBAdapt( RGB_clip, \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#---------- Last pass : bias curve process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 4+16)
#----------- RGB corrections calcul
dr_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_0) * RCS_Ave_0/float(RCS_MinMaxDiff_0)
dg_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_1) * RCS_Ave_1/float(RCS_MinMaxDiff_1)
db_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_2) * RCS_Ave_2/float(RCS_MinMaxDiff_2)
r_bias = r_bias + dr_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = g_bias + dg_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = b_bias + db_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip, \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#--------- Final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
(!show_info)? last : last\
.Subtitle("Red value : "+\
"\nDeparture"+\
"\nAverage :" + String(r_Ave) + " Median : " + String(r_Med) + " Min/max : " + String(r_MinMaxDiff)\
+ " Min : " + String(r_Min)+ " Max : " + String(r_Max)+\
"\n R_bias : " + String(r_bias) + " R_gain : " + String(r_gain) + " R_rpow : " + String(yr)+\
"\n R_spow : " + String(sr) + " R_spmid : " + String(r_spmid) + " R_pord : " + String(r_pord)+\
"\nFinish"+\
"\nAverage :" + String(RCS_Ave_0) + " Median : " + String(RCS_Med_0) + " Min/max : " + String(RCS_MinMaxDiff_0)\
+ " Min : " + String(RCS_Min_0)+ " Max : " + String(RCS_Max_0)\
,y=60,lsp=20)\
.Subtitle("Green value : "+\
"\nDeparture"+\
"\nAverage :" + String(g_Ave) + " Median : " + String(g_Med) + " Min/max : " + String(g_MinMaxDiff)\
+ " Min : " + String(g_Min)+ " Max : " + String(g_Max)+\
"\n G_bias : " + String(g_bias) + " G_gain : " + String(g_gain) + " G_rpow : " + String(yg)+\
"\n G_spow : " + String(sg) + " G_spmid : " + String(g_spmid) + " G_pord : " + String(g_pord)+\
"\nFinish"+\
"\nAverage :" + String(RCS_Ave_1) + " Median : " + String(RCS_Med_1) + " Min/max : " + String(RCS_MinMaxDiff_1)\
+ " Min : " + String(RCS_Min_1)+ " Max : " + String(RCS_Max_1)\
,y=210,lsp=20)\
.Subtitle("Blue value : "+\
"\nDeparture"+\
"\nAverage :" + String(b_Ave) + " Median : " + String(b_Med) + " Min/max : " + String(b_MinMaxDiff)\
+ " Min : " + String(b_Min)+ " Max : " + String(b_Max)+\
"\n B_bias : " + String(b_bias) + " B_gain : " + String(b_gain) + " B_rpow : " + String(yb)+\
"\n B_spow : " + String(sb) + " B_spmid : " + String(b_spmid) + " B_pord : " + String(b_pord)+\
"\nFinish"+\
"\nAverage :" + String(RCS_Ave_2) + " Median : " + String(RCS_Med_2) + " Min/max : " + String(RCS_MinMaxDiff_2)\
+ " Min : " + String(RCS_Min_2)+ " Max : " + String(RCS_Max_2)\
, y=360,lsp=20)
#-------- display scrutinized aera
scrutinized_green = BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
(!show_scrutinized)? last : scrutinized
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
return last """, args = "clip, matrix, show_info, show_scrutinized, x, y, w , h, threshold, spow")
}
StainlessS
2nd August 2016, 23:04
Please forgive me Berni, been a bit busy.
Bernardd
3rd August 2016, 10:31
Hello Stainless,
I am sad, i have believed you are in holyday.
Seriously, other tests give other script. The change is on gamma input's channel ponderation.
function RGBAdapt_auto_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
float "threshold", bool "spow")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1584313#post1584313 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
Assert(IsYV12(clip) || IsRGB(clip)," Input video colorspace must be YV12 or RGB, not YUV")
matrix = string(Default(matrix, "Rec601") ) # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
show_scrutinized = Default(show_scrutinized, false) # show scrutinized aera or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.00)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(x>=0.00 && x <= 0.99,"RGBAdapt_auto_awb: x 0.00 -> 0.99")
y = float(Default(y,0.00)) #heignt percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(y>=0.00 && y <= 0.99,"RGBAdapt_auto_awb: y 0.00 -> 0.99")
w = float(Default(w,0.00)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(w>=0.00 && w <= 0.99,"RGBAdapt_auto_awb: w 0.00 -> 0.99")
Assert(x+w>=0.00 && x+w <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
h = float(Default(h,0.00)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(h>=0.00 && h <= 0.99,"RGBAdapt_auto_awb: h 0.00 -> 0.99")
Assert(y+h>=0.00 && y+h <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
threshold = Float(Default(threshold, 0.50)) # threshold arg of y, u anv v plane AviSynth runtime functions
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.00 -> 1.00")
spow = Default(spow, false) # enable Spow process or not, default false
ScriptClip(clip, """
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#---------- Convert to RGB color space
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#---------- First pass : autogain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
#----- extraction for final display
r_Min = RCS_Min_0 g_min = RCS_Min_1 b_min = RCS_Min_2
r_Max = RCS_Max_0 g_max = RCS_Max_1 b_max = RCS_Max_2
r_MinmaxDiff = RCS_MinMaxDiff_0 g_minMaxDiff = RCS_MinMaxDiff_1 b_MinMaxDiff = RCS_max_2
r_Med = RCS_Med_0 g_Med = RCS_Med_1 b_Med = RCS_Med_2
r_Ave = RCS_Ave_0 g_Ave = RCS_Ave_1 b_Ave = RCS_Ave_2
#---- autogain process
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) # to avoid division by 0
RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01)
RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
r_gain = float(255.0/RCS_MinMaxDiff_0)
r_gain = Min (8.0, Max (r_gain, -8.0))
r_gain_limited = float(255.0/RCS_Max_0)
r_gain_limited = Min (8.0, Max (r_gain_limited, -8.0))
r_bias = - RCS_Min_0 * r_gain_limited * RCS_Max_0/float(RCS_MinMaxDiff_0)
r_bias = Min (512.0, Max (r_bias, -512.0))
g_gain = float(255.0/RCS_MinMaxDiff_1)
g_gain = Min (8.0, Max (g_gain, -8.0))
g_gain_limited = float(255.0/RCS_Max_1)
g_gain_limited = Min (8.0, Max (g_gain_limited, -8.0))
g_bias = - RCS_Min_1 * g_gain_limited * RCS_Max_1/float(RCS_MinMaxDiff_1)
g_bias = Min (512.0, Max (g_bias, -512.0))
b_gain = float(255.0/RCS_MinMaxDiff_2)
b_gain = Min (8.0, Max (b_gain, -8.0))
b_gain_limited = float(255.0/RCS_Max_2)
b_gain_limited = Min (8.0, Max (b_gain_limited, -8.0))
b_bias = - RCS_Min_2 * b_gain_limited * RCS_Max_2/float(RCS_MinMaxDiff_2)
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip,\
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = 1.0, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = 1.0, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = 1.0, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
#---------- Second pass : gamma curves process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 4+16)
#----------- RGB corrections values calcul
dr = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_0) * 3 * RCS_MinMaxDiff_0/float(RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2)
dg = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_1) * 3 * RCS_MinMaxDiff_1/float(RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2)
db = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_2) * 3 * RCS_MinMaxDiff_2/float(RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2)
#----- RGB correction with Rpow curve calcul
yr = pow(4.0,dr/128.0)
yr = Min (4.0, Max (yr, 0.1))
yg = pow(4.0,dg/128.0)
yg = Min (4.0, Max (yg, 0.1))
yb = pow(4.0,db/128.0)
yb = Min (4.0, Max (yb, 0.1))
RGBAdapt( RGB_clip, \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = yr, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = yg, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = yb, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
#---------- Third pass : spow curves process experimental based on channel average and median difference value
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 8+16)
#----------- RGB correction with Spow curve calcul ---- Experimental
sr = (Spow == true) ? pow(4.0,(RCS_Med_0/float(RCS_Ave_0)) * dr/256.0) : 1.0
sr = Min (4.0, Max (sr, 0.1))
sg = (Spow == true) ? pow(4.0,(RCS_Med_1/float(RCS_Ave_1)) * dg/256.0) : 1.0
sg = Min (4.0, Max (sg, 0.1))
sb = (Spow == true) ? pow(4.0,(RCS_Med_2/float(RCS_Ave_2)) * db/256.0) : 1.0
#--------- Spmid calcul
r_spmid = 0.5 * (float(RCS_Med_0/RCS_Ave_0))
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = 0.5 * (float(RCS_Med_1)/RCS_Ave_1)
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = 0.5 * (float(RCS_Med_2)/RCS_Ave_2)
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#------- Pord calcul
r_pord = (RCS_Med_0>RCS_Ave_0) ? true : false
g_pord = (RCS_Med_1>RCS_Ave_1) ? true : false
b_pord = (RCS_Med_2>RCS_Ave_2) ? true : false
RGBAdapt( RGB_clip, \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#---------- Last pass : bias curve process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 4+16)
#----------- RGB corrections calcul
dr_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_0) * RCS_Ave_0/float(RCS_MinMaxDiff_0)
dg_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_1) * RCS_Ave_1/float(RCS_MinMaxDiff_1)
db_bias = ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3 - RCS_Ave_2) * RCS_Ave_2/float(RCS_MinMaxDiff_2)
r_bias = r_bias + dr_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = g_bias + dg_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = b_bias + db_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip, \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = 1.0, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = r_pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = 1.0, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = g_pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = 1.0, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = b_pord)
#--------- Final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
(!show_info)? last : last\
.Subtitle("Red value : "+\
"\nDeparture"+\
"\nAverage :" + String(r_Ave) + " Median : " + String(r_Med) + " Min/max : " + String(r_MinMaxDiff)\
+ " Min : " + String(r_Min)+ " Max : " + String(r_Max)+\
"\n R_bias : " + String(r_bias) + " R_gain : " + String(r_gain) + " R_rpow : " + String(yr)+\
"\n R_spow : " + String(sr) + " R_spmid : " + String(r_spmid) + " R_pord : " + String(r_pord)+\
"\nFinish"+\
"\nAverage :" + String(RCS_Ave_0) + " Median : " + String(RCS_Med_0) + " Min/max : " + String(RCS_MinMaxDiff_0)\
+ " Min : " + String(RCS_Min_0)+ " Max : " + String(RCS_Max_0)\
,y=60,lsp=20)\
.Subtitle("Green value : "+\
"\nDeparture"+\
"\nAverage :" + String(g_Ave) + " Median : " + String(g_Med) + " Min/max : " + String(g_MinMaxDiff)\
+ " Min : " + String(g_Min)+ " Max : " + String(g_Max)+\
"\n G_bias : " + String(g_bias) + " G_gain : " + String(g_gain) + " G_rpow : " + String(yg)+\
"\n G_spow : " + String(sg) + " G_spmid : " + String(g_spmid) + " G_pord : " + String(g_pord)+\
"\nFinish"+\
"\nAverage :" + String(RCS_Ave_1) + " Median : " + String(RCS_Med_1) + " Min/max : " + String(RCS_MinMaxDiff_1)\
+ " Min : " + String(RCS_Min_1)+ " Max : " + String(RCS_Max_1)\
,y=210,lsp=20)\
.Subtitle("Blue value : "+\
"\nDeparture"+\
"\nAverage :" + String(b_Ave) + " Median : " + String(b_Med) + " Min/max : " + String(b_MinMaxDiff)\
+ " Min : " + String(b_Min)+ " Max : " + String(b_Max)+\
"\n B_bias : " + String(b_bias) + " B_gain : " + String(b_gain) + " B_rpow : " + String(yb)+\
"\n B_spow : " + String(sb) + " B_spmid : " + String(b_spmid) + " B_pord : " + String(b_pord)+\
"\nFinish"+\
"\nAverage :" + String(RCS_Ave_2) + " Median : " + String(RCS_Med_2) + " Min/max : " + String(RCS_MinMaxDiff_2)\
+ " Min : " + String(RCS_Min_2)+ " Max : " + String(RCS_Max_2)\
, y=360,lsp=20)
#-------- display scrutinized aera
scrutinized_green = BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
(!show_scrutinized)? last : scrutinized
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
return last """, args = "clip, matrix, show_info, show_scrutinized, x, y, w , h, threshold, spow")
}
Bernardd
26th August 2016, 21:41
Hello,
In following post, is a new version of the script. And yes again, but I think it is one that gives the most useful results.
The parameters are:
as usual the RT_Stats args
- The coordinates x, y, w and h to define the area to be analyzed
- Threshold for defining a percentage threshold at which the pixel values will be considered for the extraction of color channel values
- A toggle to enable autogain (default true). As Dani had shown all starts with the work of the gain, disabling this treatment is right for the curious.
- A toggle to turn the auto-contrast. activation needed to increase automatic process that help make the white balance. (default true).
But this action, if it saturates the colors, also enhances dark areas and amplifies the clear area, so can lead to a loss of information in the dark and into the light.
His profit is therefore not automatic.
- A toggle to enable automatic weighting of contrast. Activate default, it minimizes the risk of loss of information cited above.
- An adjustment parameter of the strength of the automatic weighting. By default set to 1, ie automatic weighting base, it can be decreased to 0 or increased to 2.
This parameter shows the interest to personalize this weighting. For undisturbed videos here does not change much, for difficult cases may be a way of refinement.
- Rpow a toggle to enable gamma treatment
- A SPoW toggle to enable the treatment of gamma-type with an inflection point. Allows saturate the colors and shadows unfortunately, like contrast the benefit is not automatic
- A pord toggle to define whether the rpow treatment is carried out first (default: false) or second when the value is true. Normally not to touch
- A bias toggle to activate the final treatment by shifting the values in according with the theory of the gray world. Disabling this process is just for the curious. But not completely,
with only this enabled flip you get a very close balance of whites than ColorYUV, so you can check that applying the theory of gray world in RGB range with
base on the average of the mean values of each channel is equivalent to the base 128 in YUV.
With this new script, you can use only classical autogain and autobias process, with benefit results with low chroma shift videos.
With hight chroma shift, you must use autocont and after rpow.
In default mode, whole process are enable. With low chroma shift videos gamma correction are little.
Samples
Lena, left side original, result of old script version (deprecated), result of new script version with default, result of new script version with autocont disable and result of the new script version with only
automatic weighting of contrast disable
http://img110.xooimage.com/files/5/2/7/lena-2-503d55b.jpg (http://letransfert.soforums.com/image/110/5/2/7/lena-2-503d55b.jpg.htm)
Four Fred pictures copied ( http://forum.doom9.org/showthread.php?p=1777868#post1777868 ). These are results of the default of the script. Only for the second in left, where spow has been desable to decrease
the very light green chroma shift.
http://img110.xooimage.com/files/d/b/5/grece-quatre-503d5d8.jpg (http://letransfert.soforums.com/image/110/d/b/5/grece-quatre-503d5d8.jpg.htm)
Bernardd
26th August 2016, 21:43
Below the script
function RGBAdapt_auto_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
bool "autogain", float "threshold", bool "autocont", bool "ponderated_autocont", float "autocont_strength", \
bool "rpow", bool "spow", bool "pord", bool "bias")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1584313#post1584313 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
Assert(IsYV12(clip) || IsRGB(clip)," Input video colorspace must be YV12 or RGB, not YUV")
matrix = string(Default(matrix, "Rec601") ) # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
show_scrutinized = Default(show_scrutinized, false) # show scrutinized aera or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.00)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(x>=0.00 && x <= 0.99,"RGBAdapt_auto_awb: x 0.00 -> 0.99")
y = float(Default(y,0.00)) #heignt percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(y>=0.00 && y <= 0.99,"RGBAdapt_auto_awb: y 0.00 -> 0.99")
w = float(Default(w,0.00)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(w>=0.00 && w <= 0.99,"RGBAdapt_auto_awb: w 0.00 -> 0.99")
Assert(x+w>=0.00 && x+w <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
h = float(Default(h,0.00)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(h>=0.00 && h <= 0.99,"RGBAdapt_auto_awb: h 0.00 -> 0.99")
Assert(y+h>=0.00 && y+h <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.00 -> 1.00")
autogain = Default(autogain, true) # enable autogain process or not,
autocont = Default(autocont, true) # enable autocont process or not,
ponderated_autocont = Default(ponderated_autocont, true) # enable autocont with ponderation factor process or not,
autocont_strength = Float(Default(autocont_strength, 1.0)) # strength arg for automatic ponderation factor
Assert(autocont_strength>=0.00 && autocont_strength <= 2.00,"RGBAdapt_auto_awb: autocont_strength 0.00 -> 2.00")
rpow = Default(rpow, true) # enable rpow process or not
spow = Default(spow, true) # enable Spow process or not
pord = Default(pord, false) # RGBAdapt pord arg
bias = Default(bias, true) # enable Spow process or not
ScriptClip(clip, """
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#---------- Convert to RGB color space
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#---------- First pass : autogain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
#----- extraction for gain/cont calculation and final display
r_Min = RCS_Min_0 g_min = RCS_Min_1 b_min = RCS_Min_2
r_Max = RCS_Max_0 g_max = RCS_Max_1 b_max = RCS_Max_2
r_MinmaxDiff = RCS_MinMaxDiff_0 g_minMaxDiff = RCS_MinMaxDiff_1 b_MinMaxDiff = RCS_MinMaxDiff_2
r_Ave = RCS_Ave_0 g_Ave = RCS_Ave_1 b_Ave = RCS_Ave_2
#----------- RGB corrections values calcul
#---- autogain process
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) # to avoid division by 0
RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01)
RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
#---- note : The RCS_min == RCS_max conditions below are only to keep color of BlankClip
ave = RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2
r_gain = (!autogain) ? 1.0 : ((RCS_Min_0 == RCS_Max_0) ? 1.0 : float(255.0/RCS_MinMaxDiff_0))
r_gain = Min (8.0, Max (r_gain, -8.0))
r_gain_bias = (!autogain) ? 0 : ((RCS_Min_0 == RCS_Max_0) ? 0.0 : - RCS_Min_0 * r_gain)
g_gain = (!autogain) ? 1.0 : ((RCS_Min_1 == RCS_Max_1) ? 1.0 : float(255.0/RCS_MinMaxDiff_1))
g_gain = Min (8.0, Max (g_gain, -8.0))
g_gain_bias = (!autogain) ? 0 : ((RCS_Min_1 == RCS_Max_1) ? 0.0 : - RCS_Min_1 * g_gain)
b_gain = (!autogain) ? 1.0 : ((RCS_Min_2 == RCS_Max_2) ? 1.0 : float(255.0/RCS_MinMaxDiff_2))
b_gain = Min (8.0, Max (b_gain, -8.0))
b_gain_bias = (!autogain) ? 0 : ((RCS_Min_2 == RCS_Max_2) ? 0.0 : - RCS_Min_2 * b_gain)
new_ave = (RCS_Ave_0 * r_gain + RCS_Ave_1 * g_gain + RCS_Ave_2* b_gain)
#---- autocont process
r_cont = (!autocont) ? 1.0 : ((!ponderated_autocont) ? r_gain : r_gain * ave/new_ave * autocont_strength )
g_cont = (!autocont) ? 1.0 : ((!ponderated_autocont) ? g_gain : g_gain * ave/new_ave * autocont_strength )
b_cont = (!autocont) ? 1.0 : ((!ponderated_autocont) ? b_gain : b_gain * ave/new_ave * autocont_strength )
#---- RGBAdapt args boundaries adjustement
r_gain_bias = Min (512.0, Max (r_gain_bias, -512.0))
g_gain_bias = Min (512.0, Max (g_gain_bias, -512.0))
b_gain_bias = Min (512.0, Max (b_gain_bias, -512.0))
RGBAdapt( RGB_clip,\
R_Bias = r_gain_bias, R_Gain = r_gain, R_Cont = r_cont, R_RPow = 1.0, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false,\
G_Bias = g_gain_bias, G_Gain = g_gain, G_Cont = g_cont, G_RPow = 1.0, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = b_gain_bias, B_Gain = b_gain, B_Cont = b_cont, B_RPow = 1.0, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
#---------- Second pass : gamma curves process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
#----------- RGB corrections values calcul
ref = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3
# In gray world theory, in YUV range, ref = 128, but in RGB range average of channel average values
# is better
dr = ref - RCS_Ave_0
dg = ref - RCS_Ave_1
db = ref - RCS_Ave_2
#----- RGB correction with Rpow curve calcul
# nota : better result when gamma process is increased with hight channel average and decreased with low average
yr = (!rpow) ? 1.0 : pow(4.0,dr/128.0) * RCS_Ave_0 / ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3)
yr = Min (4.0, Max (yr, 0.1))
yg = (!rpow) ? 1.0 : pow(4.0,dg/128.0) * RCS_Ave_1 / ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3)
yg = Min (4.0, Max (yg, 0.1))
yb = (!rpow) ? 1.0 : pow(4.0,db/128.0) * RCS_Ave_2 / ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul ----
#------- Spow process is enable in default mode. spow process increase
#------- rpow process action, thus we get more color saturation but also more dark aeras.
sr = (!spow) ? 1.0 : 1/yr
sr = Min (4.0, Max (sr, 0.1))
sg = (!spow) ? 1.0 : 1/yg
sg = Min (4.0, Max (sg, 0.1))
sb = (!spow) ? 1.0 : 1/yb
sb = Min (4.0, Max (sb, 0.1))
r_spmid = (!spow) ? 0.5 : RCS_Ave_0/255.0
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = (!spow) ? 0.5 : RCS_Ave_1/255.0
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = (!spow) ? 0.5 : RCS_Ave_2/255.0
b_spmid = Min (0.99, Max (b_spmid, 0.01))
RGBAdapt( RGB_clip, \
R_Bias = r_gain_bias, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = pord,\
G_Bias = g_gain_bias, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = pord,\
B_Bias = b_gain_bias, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = pord)
#---------- Last pass : bias curve process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
#----------- RGB corrections calcul
ref = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3
# In gray world theory, in YUV range, ref = 128, but in RGB range average of channel average values
# is better
dr_bias = (!bias) ? 0.0 : ((RCS_Min_0 == RCS_Max_0) ? 0.0 : ref - RCS_Ave_0)
dg_bias = (!bias) ? 0.0 : ((RCS_Min_1 == RCS_Max_1) ? 0.0 : ref - RCS_Ave_1)
db_bias = (!bias) ? 0.0 : ((RCS_Min_2 == RCS_Max_2) ? 0.0 : ref - RCS_Ave_2)
r_bias = r_gain_bias + dr_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = g_gain_bias + dg_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = b_gain_bias + db_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip, \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = pord)
#--------- Final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
(!show_info)? last : last\
.Subtitle("Red value : "+ \
"\nDeparture : " + " Average : " + String(r_Ave) + " Min/max : " + String(r_MinMaxDiff)\
+ " Min : " + String(r_Min)+ " Max : " + String(r_Max)+\
"\n R_bias : " + String(r_bias) + " R_gain : " + String(r_gain) + " R_cont : " + String(r_cont) +\
"\n R_rpow : " + String(yr )+ " R_spow : " + String(sr) + " R_spmid : " + String(r_spmid)+\
"\nFinish : " + " Average : " + String(RCS_Ave_0) + " Min/max : " + String(RCS_MinMaxDiff_0)\
+ " Min : " + String(RCS_Min_0)+ " Max : " + String(RCS_Max_0)\
, y= 60, lsp= 20, text_color = $00FFFF00, halo_color = $00000000)\
.Subtitle("Green value : "+\
"\nDeparture : "+ " Average : " + String(g_Ave) + " Min/max : " + String(g_MinMaxDiff)\
+ " Min : " + String(g_Min)+ " Max : " + String(g_Max)+\
"\n G_bias : " + String(g_bias) + " G_gain : " + String(g_gain) + " G_cont : " + String(g_cont)+\
"\n G_rpow : " + String(yg) + " G_spow : " + String(sg) + " G_spmid : " + String(g_spmid) +\
"\nFinish : " + " Average : " + String(RCS_Ave_1) + " Min/max : " + String(RCS_MinMaxDiff_1)\
+ " Min : " + String(RCS_Min_1)+ " Max : " + String(RCS_Max_1)\
, y= 210, lsp= 20, text_color = $00FFFF00, halo_color = $00000000)\
.Subtitle("Blue value : "+\
"\nDeparture" + " Average : " + String(b_Ave) + " Min/max : " + String(b_MinMaxDiff)\
+ " Min : " + String(b_Min)+ " Max : " + String(b_Max)+\
"\n B_bias : " + String(b_bias) + " B_gain : " + String(b_gain)+ " B_cont : " + String(b_cont) +\
"\n B_rpow : " + String(yb) + " B_spow : " + String(sb) + " B_spmid : " + String(b_spmid) +\
"\nFinish : " + " Average :" + String(RCS_Ave_2) + " Min/max : " + String(RCS_MinMaxDiff_2)\
+ " Min : " + String(RCS_Min_2)+ " Max : " + String(RCS_Max_2)\
, y = 360, lsp = 20, text_color = $00FFFF00, halo_color = $00000000)
#-------- display scrutinized aera
scrutinized_green = BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
(!show_scrutinized)? last : scrutinized
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
return last """, args = "clip, matrix, show_info, show_scrutinized, x, y, w , h, autogain, threshold, autocont, ponderated_autocont, autocont_strength,"+\
" rpow, spow, pord, bias")
}
Bernard
Bernardd
1st September 2016, 16:10
Hello here is the latest version of my script.
The amendments concern at the treatment of auto-contrast.
In the previous version the autocontraste was being a toggle to activate it, a toggle to activate a weighting and a setting to adjust weighting.
Today it is now adjustable from 0.0 to 1.0 by varying the strength of action of its treatment
and 0.0 means auto-contrast disabled and 1.0 enabledat full power
This setting is now complemented by the respective weight adjustment of luma and chroma coding in each channel
This setting varies from 0.0 to 1.0
0.0 No change 1.0 limit the treatment to the theoretical value of the chroma range for each channel between the two that is a percentage.
This contrast setting is active even if the previous contrast setting is disabled.
In practice the latter setting allows you to find the green.
In the following message doom9 examples from a beautiful cover of colors with ColorMill plugin VirtualDub were broadcast
http://forum.doom9.org/showthread.php?p=1745309#post1745309
Here the action of the script on the original images, copied to the site
The bottom right window is auto-contrast and set luma_chroma = 0.4
http://img110.xooimage.com/files/6/2/b/compared1_1-50495c0.jpg (http://letransfert.soforums.com/image/110/6/2/b/compared1_1-50495c0.jpg.htm)
http://img110.xooimage.com/files/6/8/a/compared2_1-50495c5.jpg (http://letransfert.soforums.com/image/110/6/8/a/compared2_1-50495c5.jpg.htm)
http://img110.xooimage.com/files/3/7/4/compared3_1-50495c9.jpg (http://letransfert.soforums.com/image/110/3/7/4/compared3_1-50495c9.jpg.htm)
http://img110.xooimage.com/files/c/e/0/compared4_1-50495d3.jpg (http://letransfert.soforums.com/image/110/c/e/0/compared4_1-50495d3.jpg.htm)
http://img110.xooimage.com/files/a/8/5/compared5_1-50495d8.jpg (http://letransfert.soforums.com/image/110/a/8/5/compared5_1-50495d8.jpg.htm)
http://img110.xooimage.com/files/a/5/3/compared6_1-50495e1.jpg (http://letransfert.soforums.com/image/110/a/5/3/compared6_1-50495e1.jpg.htm)
The reds are not as sharp as examples posted on doom. But do not forget that the script worked on copied images on the web
and with ColorMill can be added color saturation.
Here is another illustration green recovery with a picture posted by Fred with auto-contrast 1.0-luma and chroma 0.5
http://img110.xooimage.com/files/5/8/a/fred_1-50495e9.jpg (http://letransfert.soforums.com/image/110/5/8/a/fred_1-50495e9.jpg.htm)
Looking at these images, it is questionable whether the auto-contrast treatment and rpow and SPoW are really necessary.
For easy videos, the answer is no, but for difficult cases yes.
Here is a case where everything is on the bottom right window corresponds to luma_chroma = 1.0 (whole process)
http://img110.xooimage.com/files/f/2/e/tahiti-5434_1-50495f8.jpg (http://letransfert.soforums.com/image/110/f/2/e/tahiti-5434_1-50495f8.jpg.htm)
The script is in following post
Bernard
Bernardd
1st September 2016, 16:15
The lines to call the function (and proposal lines for AvsPmod user sliders)
AVISource("C:\........you_video.avi")
LoadPlugin("C:\........\GRunT.dll")
LoadPlugin("C:\........\RGBAdapt.dll")
LoadPlugin("C:\........\RT_Stats26.dll")
# display tunings
comparison = true
show_scrutinized = true
show_info = false
# color space matrix tuning and specify the source rectangle under scrutiny
matrix = "Rec601"
x = 0.09
Y= 0.09
w = 0.09
h = 0.09
# autogain tunings
threshold = 0.10
autogain = true
# autocontraste tunings
autocont_strength = 1.0
luma_chroma = 0.0
# gamma process tunings
rpow = true
spow = true
pord = false
# bias tuning
bias = true
# If you use AvsPmod user sliders you can delete comment for follow lines
#~ [<separator="display tunings">]
#~ comparison = Select([<"show different settings - (false ou true) default = false = 0", 0, 1, 1>], false , true)
#~ show_scrutinized = Select([<"show scrutinized aera - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_info = Select([<"show datas - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="color space matrix tuning and specify the source rectangle under scrutiny">]
#~ matrix = Select([<"color matrix - (Rec 601= 0 ou Rec 709 =1) = default = 0", 0, 1, 0>], "Rec601" , "Rec709")
#~ x = [<"ignore pixels on left - width percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ Y= [<"ignore pixels on top - heigth percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ w = [<"ignore pixels on right - width percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ h = [<"ignore pixels on bottom - heigth percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ [<separator="automatic white balance tunings">]
#~ [<separator="-------- autogain tunings">]
#~ threshold = [<"percentage for extreme pixels to be ignored - default : 0.10", 0.00, 1.00, 0.1>]
#~ autogain = Select([<"enable autogain process - (false or true) default = false = 0", 0, 1, 1>], false , true)
#~ [<separator="-------- autocontraste tunings">]
#~ autocont_strength = [<"enable and strength action auto-cont process (0.0 = desable 1.0 = full) - default : 1.0", 0.0, 1.0, 0.4>]
#~ luma_chroma = [<"channel luma vs chroma weigth adjust (0.0 = desable 1.0 = full) - default : 0.0", 0.0, 1.0, 0.4>]
#~ [<separator="-------- gamma process tunings">]
#~ rpow = Select([<"enable rpow process - (false or true) default = true = 0", 0, 1, 1>], false , true)
#~ spow = Select([<"enable spow process - (false or true) default = true = 0", 0, 1, 1>], false , true)
#~ pord = Select([<"Pord - (false = rpow before spow ) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="-------- bias tuning">]
#~ bias = Select([<"enable bias process - (false or true) default = false = 0", 0, 1, 1>], false , true)
output = RGBAdapt_auto_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold = threshold, autogain = autogain, luma_chroma = luma_chroma, \
autocont_strength = autocont_strength, rpow = rpow, spow = spow, pord = pord, bias = bias)
without_autocont_output = RGBAdapt_auto_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, autocont_strength = 0.0, luma_chroma = 0.0)\
. Subtitle ("gain, rpow, spow and bias no auto cont")
bias_only = RGBAdapt_auto_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, autogain = false, autocont_strength = 0.0, luma_chroma = 0.0, rpow = false)\
. Subtitle ("bias only (ColorYUV autowhite)")
gain_bias_only = RGBAdapt_auto_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, autocont_strength = 0.0, luma_chroma = 0.0, rpow = false). Subtitle ("gain and bias only")
whole = RGBAdapt_auto_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, luma_chroma = 0.0)\
. Subtitle ("gain cont (default) rpow spow and bias")
compared_output = StackVertical(StackHorizontal(last.Subtitle("original"),gain_bias_only, whole), \
StackHorizontal(bias_only, without_autocont_output, output. Subtitle ("user setting")))
(!comparison) ? output : compared_output
return last
The lines for the function in the following post
Bernard
Bernardd
1st September 2016, 16:18
# ---------------------------- function script ------------------------------------
function RGBAdapt_auto_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
float "threshold", bool "autogain", float "luma_chroma" , float "autocont_strength", \
bool "rpow", bool "spow", bool "pord", bool "bias")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1584313#post1584313 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
Assert(IsYV12(clip) || IsRGB(clip)," Input video colorspace must be YV12 or RGB, not YUV")
matrix = string(Default(matrix, "Rec601") ) # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
show_scrutinized = Default(show_scrutinized, false) # show scrutinized aera or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.00)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(x>=0.00 && x <= 0.99,"RGBAdapt_auto_awb: x 0.00 -> 0.99")
y = float(Default(y,0.00)) #heignt percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(y>=0.00 && y <= 0.99,"RGBAdapt_auto_awb: y 0.00 -> 0.99")
w = float(Default(w,0.00)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(w>=0.00 && w <= 0.99,"RGBAdapt_auto_awb: w 0.00 -> 0.99")
Assert(x+w>=0.00 && x+w <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
h = float(Default(h,0.00)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(h>=0.00 && h <= 0.99,"RGBAdapt_auto_awb: h 0.00 -> 0.99")
Assert(y+h>=0.00 && y+h <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.00 -> 1.00")
autogain = Default(autogain, true) # enable autogain process or not, default false
autocont_strength = Float(Default(autocont_strength, 1.0)) # strength arg for automatic ponderation factor
Assert(autocont_strength>=0.00 && autocont_strength <= 1.00,"RGBAdapt_auto_awb: autocont_strength 0.00 -> 1.00")
luma_chroma = Float(Default(luma_chroma, 0.00)) # strength arg for automatic ponderation factor
Assert(luma_chroma>=0.00 && luma_chroma <= 1.00,"RGBAdapt_auto_awb: luma_chroma 0.00 -> 1.00")
rpow = Default(rpow, true) # enable rpow process or not,
spow = Default(spow, true) # enable Spow process or not,
pord = Default(pord, false) # RGBAdapt pord arg
bias = Default(bias, true) # enable Spow process or not,
ScriptClip(clip, """
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#---------- Convert to RGB color space
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#---------- First pass : autogain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
#----- extraction for gain/cont calculation and final display
r_Min = RCS_Min_0 g_min = RCS_Min_1 b_min = RCS_Min_2
r_Max = RCS_Max_0 g_max = RCS_Max_1 b_max = RCS_Max_2
r_MinmaxDiff = RCS_MinMaxDiff_0 g_minMaxDiff = RCS_MinMaxDiff_1 b_MinMaxDiff = RCS_MinMaxDiff_2
r_Ave = RCS_Ave_0 g_Ave = RCS_Ave_1 b_Ave = RCS_Ave_2
#----------- RGB corrections values calcul
#---- autogain process
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) # to avoid division by 0
RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01)
RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
#---- note : The RCS_min == RCS_max conditions below are only to keep color of BlankClip
som_diff = (RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2)/3
som_som = (RCS_Max_0 + RCS_Min_0 + RCS_Max_1 + RCS_Min_1 + RCS_Max_2 + RCS_Min_2)/3
r_gain = (!autogain) ? 1.0 : ((RCS_Min_0 == RCS_Max_0) ? 1.0 : float(255.0/RCS_MinMaxDiff_0))
r_gain = Min (8.0, Max (r_gain, -8.0))
r_gain_bias = (!autogain) ? 0 : ((RCS_Min_0 == RCS_Max_0) ? 0.0 : - RCS_Min_0 * r_gain)
g_gain = (!autogain) ? 1.0 : ((RCS_Min_1 == RCS_Max_1) ? 1.0 : float(255.0/RCS_MinMaxDiff_1))
g_gain = Min (8.0, Max (g_gain, -8.0))
g_gain_bias = (!autogain) ? 0 : ((RCS_Min_1 == RCS_Max_1) ? 0.0 : - RCS_Min_1 * g_gain)
b_gain = (!autogain) ? 1.0 : ((RCS_Min_2 == RCS_Max_2) ? 1.0 : float(255.0/RCS_MinMaxDiff_2))
b_gain = Min (8.0, Max (b_gain, -8.0))
b_gain_bias = (!autogain) ? 0 : ((RCS_Min_2 == RCS_Max_2) ? 0.0 : - RCS_Min_2 * b_gain)
#---- autocont process and or manual luma weight vs chroma weight adjust for each color channel
r_cont = (1 + (r_gain - 1) * float(som_diff/som_som) * autocont_strength ) * (1 - 0.299 * luma_chroma)
g_cont = (1 + (g_gain - 1) * float(som_diff/som_som) * autocont_strength ) * (1 - 0.587 * luma_chroma)
b_cont = (1 + (b_gain - 1) * float(som_diff/som_som) * autocont_strength ) * (1 - 0.114 * luma_chroma)
#---- RGBAdapt args boundaries adjustement
r_gain_bias = Min (512.0, Max (r_gain_bias, -512.0))
g_gain_bias = Min (512.0, Max (g_gain_bias, -512.0))
b_gain_bias = Min (512.0, Max (b_gain_bias, -512.0))
RGBAdapt( RGB_clip,\
R_Bias = r_gain_bias, R_Gain = r_gain, R_Cont = r_cont, R_RPow = 1.0, R_Spow = 1.0, R_SPMid = 0.5, R_Pord = false,\
G_Bias = g_gain_bias, G_Gain = g_gain, G_Cont = g_cont, G_RPow = 1.0, G_Spow = 1.0, G_SPMid = 0.5, G_Pord = false,\
B_Bias = b_gain_bias, B_Gain = b_gain, B_Cont = b_cont, B_RPow = 1.0, B_Spow = 1.0, B_SPMid = 0.5, B_Pord = false)
#---------- Second pass : gamma curves process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
#----------- RGB corrections values calcul
ref = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3
# In gray world theory, in YUV range, ref = 128, but in RGB range average of channel average values
# is better
dr = ref - RCS_Ave_0
dg = ref - RCS_Ave_1
db = ref - RCS_Ave_2
#----- RGB correction with Rpow curve calcul
# nota : better result when gamma process is increased with hight channel average and decreased with low average
yr = (!rpow) ? 1.0 : pow(4.0,dr/128.0) * RCS_Ave_0 / ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3)
yr = Min (4.0, Max (yr, 0.1))
yg = (!rpow) ? 1.0 : pow(4.0,dg/128.0) * RCS_Ave_1 / ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3)
yg = Min (4.0, Max (yg, 0.1))
yb = (!rpow) ? 1.0 : pow(4.0,db/128.0) * RCS_Ave_2 / ((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3)
yb = Min (4.0, Max (yb, 0.1))
#----------- RGB correction with Spow curve calcul ---- Experimental
#------- Spow process is enable in default mode, spmid and pord args default values increase
#------- rpow process action, thus we get more color saturation but also more dark aeras.
sr = (!spow) ? 1.0 : 1/yr
sr = Min (4.0, Max (sr, 0.1))
sg = (!spow) ? 1.0 : 1/yg
sg = Min (4.0, Max (sg, 0.1))
sb = (!spow) ? 1.0 : 1/yb
sb = Min (4.0, Max (sb, 0.1))
r_spmid = (!spow) ? 0.5 : RCS_Ave_0/255.0
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = (!spow) ? 0.5 : RCS_Ave_1/255.0
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = (!spow) ? 0.5 : RCS_Ave_2/255.0
b_spmid = Min (0.99, Max (b_spmid, 0.01))
RGBAdapt( RGB_clip, \
R_Bias = r_gain_bias, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = pord,\
G_Bias = g_gain_bias, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = pord,\
B_Bias = b_gain_bias, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = pord)
#---------- Last pass : bias curve process in accordance with gray world theory
#----------- RGB values extraction
RT_RgbChanStats(last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
#----------- RGB corrections calcul
ref = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3
# In gray world theory, in YUV range, ref = 128, but in RGB range average of channel average values
# is better
dr_bias = (!bias) ? 0.0 : ((RCS_Min_0 == RCS_Max_0) ? 0.0 : ref - RCS_Ave_0)
dg_bias = (!bias) ? 0.0 : ((RCS_Min_1 == RCS_Max_1) ? 0.0 : ref - RCS_Ave_1)
db_bias = (!bias) ? 0.0 : ((RCS_Min_2 == RCS_Max_2) ? 0.0 : ref - RCS_Ave_2)
r_bias = r_gain_bias + dr_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = g_gain_bias + dg_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = b_gain_bias + db_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip, \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_RPow = yr, R_Spow = sr, R_SPMid = r_spmid, R_Pord = pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_RPow = yg, G_Spow = sg, G_SPMid = g_spmid, G_Pord = pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_RPow = yb, B_Spow = sb, B_SPMid = b_spmid, B_Pord = pord)
#--------- Final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
(!show_info)? last : last\
.Subtitle("Red value : "+ \
"\nDeparture : " + " Average : " + String(r_Ave) + " Min/max : " + String(r_MinMaxDiff)\
+ " Min : " + String(r_Min)+ " Max : " + String(r_Max)+\
"\n R_bias : " + String(r_bias) + " R_gain : " + String(r_gain) + " R_cont : " + String(r_cont) +\
"\n R_rpow : " + String(yr )+ " R_spow : " + String(sr) + " R_spmid : " + String(r_spmid)+\
"\nFinish : " + " Average : " + String(RCS_Ave_0) + " Min/max : " + String(RCS_MinMaxDiff_0)\
+ " Min : " + String(RCS_Min_0)+ " Max : " + String(RCS_Max_0)\
, y= 60, lsp= 20, text_color = $00FFFF00, halo_color = $00000000, size = 20)\
.Subtitle("Green value : "+\
"\nDeparture : "+ " Average : " + String(g_Ave) + " Min/max : " + String(g_MinMaxDiff)\
+ " Min : " + String(g_Min)+ " Max : " + String(g_Max)+\
"\n G_bias : " + String(g_bias) + " G_gain : " + String(g_gain) + " G_cont : " + String(g_cont)+\
"\n G_rpow : " + String(yg) + " G_spow : " + String(sg) + " G_spmid : " + String(g_spmid) +\
"\nFinish : " + " Average : " + String(RCS_Ave_1) + " Min/max : " + String(RCS_MinMaxDiff_1)\
+ " Min : " + String(RCS_Min_1)+ " Max : " + String(RCS_Max_1)\
, y= 210, lsp= 20, text_color = $00FFFF00, halo_color = $00000000, size = 20)\
.Subtitle("Blue value : "+\
"\nDeparture" + " Average : " + String(b_Ave) + " Min/max : " + String(b_MinMaxDiff)\
+ " Min : " + String(b_Min)+ " Max : " + String(b_Max)+\
"\n B_bias : " + String(b_bias) + " B_gain : " + String(b_gain)+ " B_cont : " + String(b_cont) +\
"\n B_rpow : " + String(yb) + " B_spow : " + String(sb) + " B_spmid : " + String(b_spmid) +\
"\nFinish : " + " Average :" + String(RCS_Ave_2) + " Min/max : " + String(RCS_MinMaxDiff_2)\
+ " Min : " + String(RCS_Min_2)+ " Max : " + String(RCS_Max_2)\
, y = 360, lsp = 20, text_color = $00FFFF00, halo_color = $00000000, size = 20)
#-------- display scrutinized aera
scrutinized_green = BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
(!show_scrutinized)? last : scrutinized
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
return last """, args = "clip, matrix, show_info, show_scrutinized, x, y, w , h, autogain, threshold, autocont_strength, luma_chroma,"+\
" rpow, spow, pord, bias")
}
Bernard
StainlessS
2nd September 2016, 07:09
Nice job Bernardd.
How did you deal with the subtitled text on the images ?
Some of Fred's images have similar Subtitles which make it impossible to exactly re-create the final images (you have to crop off the nuisance text
so as not to affect results, but then have different image).
To make things worse, you add more subtitles to the images, meaning more to crop off and less like original.
Can I suggest that you add black bar top or bottom and subtitle over that, so can easily be cropped leaving original intact.
It does not look like you treated the subtitles in any way special, so maybe that threw off your corrections a little (perhaps).
EDIT: Also would be nice if images were Portable Network Graphics, png format rather than jpg, so we have the exact image that
you worked with.
StainlessS
2nd September 2016, 10:02
Here, tiny function to add sub to clip, demo'ed using GamMac script.
#Imagesource("Avenue.png",end=0)
#Imagesource("BlueFish.png",end=0)
Imagesource("ClimbingFrame.png",end=0)
#Imagesource("Cup&Saucer.png",end=0)
#Imagesource("Deer.png",end=0)
#Imagesource("Elephants.png",end=0)
#Imagesource("Fish.png",end=0)
#Imagesource("GreenChurch.png",end=0)
#Imagesource("Lenna.png",end=0)
#Imagesource("LollipopLady.png",end=0)
#Imagesource("Parrot.png",end=0)
#Imagesource("Pool.png",end=0)
#Imagesource("Puppy.png",end=0)
#Imagesource("PyramidSkier.png",end=0)
#Imagesource("Singers.png",end=0)
#Imagesource("Tahiti.png",end=0)
#Imagesource("TajMahal.png",end=0)
#Imagesource("Train.png",end=0)
#Imagesource("Unwrapping.png",end=0)
#Imagesource("WalkInThePark.png",end=0)
#Imagesource("Matt_Greece_001.png",end=0)
#Imagesource("Matt_Greece_002.png",end=0)
#Imagesource("Matt_Greece_004.png",end=0)
#Imagesource("Matt_Greece_005.png",end=0)
#Imagesource("Matt_Greece_007.png",end=0)
#Imagesource("Matt_Greece_009.png",end=0)
Function Sub(clip c,string tit) {Return StackVertical(c,c.Blankclip(Height=20).SubTitle(tit))}
ConvertToRGB24
O=Last
LockChan = 1 # Chan for lock to Ave, 0=R, 1=G, 2=B
# -1 = Use LockVal below.
# -2 = LockVal=(RedAve+GrnAve+BluAve)/3.0 for LockVal.
# -3 = LockVal=Median(RedAve,GrnAve,BluAve)
Scale=1
RedMul = 1.0 # Required Ave multiplier for Red Channel, applied when requesting GuessGamma(reqAve*RedMul),
# Even applied when LockChan=-1.
GrnMul = 1.0 # Same for Green channel. GrnMul even applies when LockChan is Green Channel, etc for chans.
BluMul = 1.0 # Same for Blue channel. Allows tinkering/fine tuning.
th = 0.0
LockVal = 8.0 # Only valid if LockChan == -1
RngLim = 10.0
GamMax = 10.0
Show = False # Subtitles
Verb = 3
x=0
y=0
w=0
h=0
Scale=0
A=GamMac(LockChan=LockChan,LockVal=LockVal,RedMul=RedMul,GrnMul=GrnMul,BluMul=BluMul,Show=Show,Verbosity=Verb,Th=Th,SCALE=SCALE,
\ RngLim=RngLim,GamMax=GamMax,x=x,y=y,w=w,h=h)
#RedMul = 0.6 Grnmul = 0.7 blumul = 0.8
Scale=1
B=GamMac(LockChan=LockChan,LockVal=LockVal,RedMul=RedMul,GrnMul=GrnMul,BluMul=BluMul,Show=Show,Verbosity=Verb,th=th,SCALE=Scale,
\ RngLim=RngLim,GamMax=GamMax,x=x,y=y,w=w,h=h)
#RedMul = 0.5 Grnmul = 0.6 blumul = 1.1
Scale=2
C=GamMac(LockChan=LockChan,LockVal=LockVal,RedMul=RedMul,GrnMul=GrnMul,BluMul=BluMul,Show=Show,Verbosity=Verb,th=th,SCALE=Scale,
\ RngLim=RngLim,GamMax=GamMax,x=x,y=y,w=w,h=h)
TOP=StackHorizontal(Sub(O,"Original"),Sub(A,"Scale 0"))
BOT=StackHorizontal(Sub(B,"Scale 1"),Sub(C,"Scale 2"))
StackVertical(TOP,BOT)
return Last
https://s20.postimg.cc/6oi93qt19/climb_zpsqisfjser.png (https://postimg.cc/image/6bquxkard/)
Subtitled black bar is 20 pixels tall at bottom of frame.
Here, zip (~6MB) with script + about 26 png's, posted in this and other threads. http://www.mediafire.com/download/rdk5du4h3c114z4/GamMacSubs.zip
All pics with Subtitles cropped off (I did not bother including images with multiple subtitles).
Bernardd
2nd September 2016, 11:36
Hello StainlessS
Do you know Rt_Stats plugin is very very powerfull ? :thanks:
I use scrutinized aera to pass through subtitle
Thanks for your tip with BlankClip and Subtitle, but now it is same fast with AddBorder.
Three pictures to illustrate the new call script, that is posted after
http://img110.xooimage.com/files/6/b/9/grece1-aera-504afaa.png (http://letransfert.soforums.com/image/110/6/b/9/grece1-aera-504afaa.png.htm)
http://img110.xooimage.com/files/8/0/4/grece1-504b140.png (http://letransfert.soforums.com/image/110/8/0/4/grece1-504b140.png.htm)
http://img110.xooimage.com/files/7/0/f/grece2-504b00c.png (http://letransfert.soforums.com/image/110/7/0/f/grece2-504b00c.png.htm)
Bernardd
2nd September 2016, 11:39
Below the call script with subtitle not on picture
AVISource("C:\........\your_video.avi")
LoadPlugin("C:\.........\GRunT.dll")
LoadPlugin("C:\.........\RGBAdapt.dll")
LoadPlugin("C:\.........\RT_Stats26.dll")
# display tunings
comparison = true
show_scrutinized = true
show_info = false
# color space matrix tuning and specify the source rectangle under scrutiny
matrix = "Rec601"
x = 0.09
Y= 0.09
w = 0.09
h = 0.09
# autogain tunings
threshold = 0.10
autogain = true
# autocontraste tunings
autocont_strength = 1.0
luma_chroma = 0.0
# gamma process tunings
rpow = true
spow = true
pord = false
# bias tuning
bias = true
# If you use AvsPmod user sliders you can delete comment for follow lines
#~ [<separator="display tunings">]
#~ comparison = Select([<"show different settings - (false ou true) default = false = 0", 0, 1, 1>], false , true)
#~ show_scrutinized = Select([<"show scrutinized aera - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_info = Select([<"show datas - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="color space matrix tuning and specify the source rectangle under scrutiny">]
#~ matrix = Select([<"color matrix - (Rec 601= 0 ou Rec 709 =1) = default = 0", 0, 1, 0>], "Rec601" , "Rec709")
#~ x = [<"ignore pixels on left - width percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ Y= [<"ignore pixels on top - heigth percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ w = [<"ignore pixels on right - width percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ h = [<"ignore pixels on bottom - heigth percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ [<separator="automatic white balance tunings">]
#~ [<separator="-------- autogain tunings">]
#~ threshold = [<"percentage for extreme pixels to be ignored - default : 0.10", 0.00, 1.00, 0.1>]
#~ autogain = Select([<"enable autogain process - (false or true) default = false = 0", 0, 1, 1>], false , true)
#~ [<separator="-------- autocontraste tunings">]
#~ autocont_strength = [<"enable and strength action auto-cont process (0.0 = desable 1.0 = full) - default : 1.0", 0.0, 1.0, 0.5>]
#~ luma_chroma = [<"channel luma vs chroma weigth adjust (0.0 = desable 1.0 = full) - default : 0.0", 0.0, 1.0, 0.2>]
#~ [<separator="-------- gamma process tunings">]
#~ rpow = Select([<"enable rpow process - (false or true) default = true = 0", 0, 1, 1>], false , true)
#~ spow = Select([<"enable spow process - (false or true) default = true = 0", 0, 1, 1>], false , true)
#~ pord = Select([<"Pord - (false = rpow before spow ) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="-------- bias tuning">]
#~ bias = Select([<"enable bias process - (false or true) default = false = 0", 0, 1, 1>], false , true)
output = RGBAdapt_auto_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold = threshold, autogain = autogain, luma_chroma = luma_chroma, \
autocont_strength = autocont_strength, rpow = rpow, spow = spow, pord = pord, bias = bias)
without_autocont_output = RGBAdapt_auto_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, autocont_strength = 0.0, luma_chroma = 0.0)\
.AddBorders(0, 20, 0, 0, color=$000000). Subtitle ("gain, rpow, spow and bias no auto cont")
bias_only = RGBAdapt_auto_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, autogain = false, autocont_strength = 0.0, luma_chroma = 0.0, rpow = false)\
.AddBorders(0, 20, 0, 0, color=$000000). Subtitle ("bias only (ColorYUV autowhite)")
gain_bias_only = RGBAdapt_auto_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, autocont_strength = 0.0, luma_chroma = 0.0, rpow = false)\
.AddBorders(0, 20, 0, 0, color=$000000). Subtitle ("gain and bias only")
whole = RGBAdapt_auto_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, luma_chroma = 0.0)\
.AddBorders(0, 20, 0, 0, color=$000000). Subtitle ("gain cont (default) rpow spow and bias")
compared_output = StackVertical(StackHorizontal(last .AddBorders(0, 20, 0, 0, color=$000000).Subtitle("original"),gain_bias_only, whole), \
StackHorizontal(bias_only, without_autocont_output, output .AddBorders(0, 20, 0, 0, color=$000000)\
. Subtitle ("user setting :" + " autocont : " + LeftStr(string(autocont_strength),3) + " luma vs chroma : " + LeftStr(string(luma_chroma),3))))
(!comparison) ? output : compared_output
return last
Bernard
Bernardd
2nd September 2016, 11:54
StainlessS
On your sample upper with GamMac, the wheel and car have near same color. With color restoration with ColorMill, the wheel are magenta and car brown.
With my script, with channel color conversion factor use, i can get a car with a little little brown tone. Have you observed the same result ?
Thanks
Bernard
StainlessS
4th September 2016, 00:15
Dont ask me about that, I've never been any good at color correction, I can spend hours tinkering and think, 'great job'.
Next day, argh, what a mess I made of that!!!.
I tend to push it too far and make it bad in opposite direction :(
Anyway, just changing BluMul in GamMac script makes side of carriage more brown, and wheel magenta (should probably be rust red).
Changed end of script as so (shows only two images), only changed BluMul to 0.93
#RedMul = 0.6 Grnmul = 0.7 blumul = 0.8
Scale=2
B=GamMac(LockChan=LockChan,LockVal=LockVal,RedMul=RedMul,GrnMul=GrnMul,BluMul=BluMul,Show=Show,Verbosity=Verb,th=th,SCALE=Scale,
\ RngLim=RngLim,GamMax=GamMax,x=x,y=y,w=w,h=h)
#RedMul = 0.5 Grnmul = 0.6 blumul = 1.1
Scale=2
RedMul=1.0 Grnmul=1.0 Blumul=0.93
C=GamMac(LockChan=LockChan,LockVal=LockVal,RedMul=RedMul,GrnMul=GrnMul,BluMul=BluMul,Show=Show,Verbosity=Verb,th=th,SCALE=Scale,
\ RngLim=RngLim,GamMax=GamMax,x=x,y=y,w=w,h=h)
#TOP=StackHorizontal(Sub(O,"Original"),Sub(A,"Scale 0"))
BOT=StackHorizontal(Sub(B,"Scale 2 : 1.00 1.00 1.00"),Sub(C,RT_String("Scale 2 : %.2f %.2f %.2f",Redmul,GrnMul,BluMul)))
#StackVertical(TOP,BOT)
BOT
return Last
The flesh tones are nowhere near as good as the RetroDisneyworld guys mod (probably easier with sliders but I dont use AvsPMod).
EDIT: The 'Night club singers' image comes out a lot darker in GamMac than RetroDisneyworld guys take, I would not be surprised
if GamMac actually got that more correct, it could well have been quite dark in that room, the Disney world guy makes it look like all the lights were on.
EDIT: Although there does seem to be a child in the audience, so could be either way.
EDIT: Or maybe RedMul=1.03 Grnmul=1.04 Blumul=0.9
videoFred
4th September 2016, 13:25
Dont ask me about that, I've never been any good at color correction, I can spend hours tinkering and think, 'great job'.
Next day, argh, what a mess I made of that!!!.
I tend to push it too far and make it bad in opposite direction :(
Sometimes, I want to correct colors from the real world hehe :p
But color correction is something you can learn by observing real colors. Especally flesh tones, vegetation and sky.
The flesh tones are nowhere near as good as the RetroDisneyworld guys mod (probably easier with sliders but I dont use AvsPMod).
What do you think about this: (subtitles added after filtering and histograms of cource)
http://www.super-8.be/Doom/disney_red_03.jpg
http://www.super-8.be/Doom/disney_red_02.jpg
http://www.super-8.be/Doom/disney_red_01.jpg
After GamMac, I adjusted red hue, yellow hue and cyan hue. Then, I did some RGB adjustments with RgbAdjust.
Talking about the Disney Guy... I do not find his postings here, does someone know where to find it?
Fred.
StainlessS
4th September 2016, 14:13
Better than I could do Fred :) (much better).
I think that in TmpGenc color correction, there was some kind of toggle button to set surrounding background Magenta (and perhaps Green), and then back to grey,
it helped to 'unskew' your color perception (which happens after staring at an image for some time).
Here is a Disney guys post, perhaps the one you search for:- http://forum.doom9.org/showthread.php?p=1745309#post1745309
And all posts by him (via Profile 'Find all posts by wdwms'):- http://forum.doom9.org/search.php?searchid=7695136
Last on-line 14 Dec 2015.
For single images, there is RGBAdjust_Graffer (with sliders), here:- http://forum.doom9.org/showthread.php?t=156774&highlight=coloryuv2
EDIT: Shekh has some kind of 6 axis rgb tweaker in his VirtualDub Mod 'vdfiltermod', here:- http://forum.doom9.org/showthread.php?t=172021
https://sourceforge.net/p/vdfiltermod/wiki/Home/attachment/sixaxis.png
EDIT: And here RgbAdapt() Graffer (this thread), much the same as RgbAdjust() but no Dither option (Added in Avisynth v2.6)
but with several additional options not available in RgbAdjust().
https://s20.postimg.cc/wxyq8spkt/Fishv3_zpsfjmoyerr.jpg (https://postimg.cc/image/yd0axiqnt/)
videoFred
4th September 2016, 15:02
Here is a Disney guys post, perhaps the one you search for:- http://forum.doom9.org/showthread.php?p=1745309#post1745309
Thank you! I did not find it in my own thread haha :D
Especially on this red films, GamMac is really a miracle filter.
Fred.
Bernardd
3rd October 2016, 19:11
Hello,
Below new script to make automatic white balance with RGBAdapt. First autogain wash the lights, second autocontrst amplify autogain process, very useful for big color cast but dangerous sometime.
After color correction in accordance with gray world theory. One correction with rpow and spow curves, one correction with bias curve. One of two or two together, it is function of video.
The function script is written in three parts to have the smaller scriptclip and so a faster script.
Script in following post
Bernardd
3rd October 2016, 19:17
The script call
AVISource("C:\ ......\ your video.avi")
LoadPlugin("C:\..........\GRunT.dll")
LoadPlugin("C:\..........\RGBAdapt.dll")
LoadPlugin("C:\..........\RT_Stats26.dll")
# display tunings
comparison = true
show_scrutinized = true
show_info = false
# color space matrix tuning and specify the source rectangle under scrutiny
matrix = "Rec601"
x = 0.09
Y= 0.09
w = 0.09
h = 0.09
# autogain tunings
threshold = 0.10
autogain = 1.0
# autocontraste tunings
autocont = 1.0
# gamma process tunings
rpow = 1.0
spow = 1.0
pord = false
# bias tuning
bias = 1.0
# If you use AvsPmod user sliders you can delete comment for follow lines
#~ [<separator="display tunings">]
#~ comparison = Select([<"show different settings - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_scrutinized = Select([<"show scrutinized aera - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_info = Select([<"show datas - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="color space matrix tuning - specify the source rectangle under scrutiny and percentage extreme pixels to ignore">]
#~ matrix = Select([<"color matrix - (Rec 601= 0 ou Rec 709 =1) = default = 0", 0, 1, 0>], "Rec601" , "Rec709")
#~ x = [<"ignore pixels on left - width percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ Y= [<"ignore pixels on top - heigth percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ w = [<"ignore pixels on right - width percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ h = [<"ignore pixels on bottom - heigth percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ threshold = [<"percentage for extreme pixels to be ignored - default : 0.10", 0.00, 1.00, 0.1>]
#~ [<separator="automatic white balance tunings">]
#~ [<separator="args autogain tunings">]
#~ autogain = [<"enable and strength autogain process - default = 1.0", 0.0, 1.0, 1.0>]
#~ [<separator="args autocontrast tunings">]
#~ autocont = [<"enable and strength autocont process - default = 1.0", 0.0, 1.0, 1.0>]
#~ [<separator="args gamma process tunings">]
#~ rpow =[<"enable and strength rpow process - default = 1.0", 0.0, 1.0, 1.0>]
#~ spow = [<"enable and strength spow process - default = 1.0", 0.0, 1.0, 1.0>]
#~ pord = Select([<"Pord - (false = rpow before spow ) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="free args bias tuning">]
#~ bias =[<"enable and strength bias process - default = 1.0", 0.0, 1.0, 1.0>]
output = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold = threshold, autogain = autogain, autocont = autocont,\
rpow = rpow, spow = spow, pord = pord, bias = bias)
without_autocont_output = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, autocont = 0.0)\
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain, rpow, spow and bias no auto cont"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " autogain strength : 1.0" + " autocont strength : 0.0" + \
"\n rpow strength : 1.0" + " spow strength : 1.0" + " pord : false" +\
"\n bias strength : 1.0" , lsp = 20)
bias_only = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, autogain = 0.0, autocont = 0.0, rpow = 0.0)\
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("bias only output near ColorYUV autowhite"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " autogain strength : 0.0" + " autocont strength : 0.0" + \
"\n rpow strength : 0.0" + " spow strength : 0.0" + " pord : false" +\
"\n bias strength : 1.0" , lsp = 20)
gain_bias_only = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, autocont = 0.0, rpow = 0.0)\
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain and bias only"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " autogain strength : 1.0" + " autocont strength : 0.0" + \
"\n rpow strength : 0.0" + " spow strength : 0.0" + " pord : false" +\
"\n bias strength : 1.0", lsp = 20)
all = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, threshold = threshold) \
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain cont rpow spow and bias"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " autogain strength : 1.0" + " autocont strength : 1.0" + \
"\n rpow strength : 1.0" + " spow strength : 1.0" + " pord : false" +\
"\n bias strength : 1.0" , lsp = 20)
compared_output = (!comparison) ? nop : StackVertical(StackHorizontal(last .AddBorders(0, 80, 0, 0, color=$000000).Subtitle("original"),gain_bias_only, all), \
StackHorizontal(bias_only, without_autocont_output, output .AddBorders(0, 80, 0, 0, color=$000000)\
. Subtitle ("user setting where all args are free" + \
"\n threshold : " + LeftStr(string(threshold),4) + " autogain strength : " + LeftStr(string(autogain),3) + " autocont strength : " + LeftStr(string(autocont),3) + \
"\n rpow strength : " + LeftStr(string(rpow),3) + " spow strength : " + LeftStr(string(spow),3) + " pord : " + string(pord) +\
"\n bias strength : " + LeftStr(string(bias),3) , lsp = 20)))
(!comparison) ? output : compared_output
Bernardd
3rd October 2016, 19:22
The script function part I
# ---------------------------- function script -------------------------------------
function RGBAdapt_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
float "threshold", float "autogain" , float "autocont", float "rpow", float "spow", bool "pord", float "bias")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1584313#post1584313 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
Assert(IsYV12(clip) || IsRGB(clip)," Input video colorspace must be YV12 or RGB, not YUV")
matrix = string(Default(matrix, "Rec601") ) # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
show_scrutinized = Default(show_scrutinized, false) # show scrutinized aera or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.00)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(x>=0.00 && x <= 0.99,"RGBAdapt_auto_awb: x 0.00 -> 0.99")
y = float(Default(y,0.00)) #heignt percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(y>=0.00 && y <= 0.99,"RGBAdapt_auto_awb: y 0.00 -> 0.99")
w = float(Default(w,0.00)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(w>=0.00 && w <= 0.99,"RGBAdapt_auto_awb: w 0.00 -> 0.99")
Assert(x+w>=0.00 && x+w <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
h = float(Default(h,0.00)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(h>=0.00 && h <= 0.99,"RGBAdapt_auto_awb: h 0.00 -> 0.99")
Assert(y+h>=0.00 && y+h <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.00 -> 1.00")
autogain = Float(Default(autogain, 1.00)) # strength arg for automatic gain
Assert(autogain>=0.00 && autogain <= 1.00,"RGBAdapt_auto_awb: autogain 0.00 -> 1.00")
autocont = Float(Default(autocont, 1.00)) # strength arg for automatic contrast
Assert(autocont>=0.00 && autocont <= 1.00,"RGBAdapt_auto_awb: autocont 0.00 -> 1.00")
rpow = Float(Default(rpow, 1.00)) # strength arg for automatic rpow
Assert(rpow>=0.00 && rpow <= 1.00,"RGBAdapt_auto_awb: rpow 0.00 -> 1.00")
spow = Float(Default(spow, 1.00)) # strength arg for automatic spow
Assert(spow>=0.00 && spow <= 1.00,"RGBAdapt_auto_awb: spow 0.00 -> 1.00")
pord = Default(pord, false) # RGBAdapt pord arg
bias = Float(Default(bias, 1.00)) # strength arg for automatic bias
Assert(bias>=0.00 && bias <= 1.00,"RGBAdapt_auto_awb: bias 0.00 -> 1.00")
#---------- Convert to RGB color space
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#--------- RGB color space process
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#--------- AWB process
ScriptClip(RGB_clip, """
#---------- First pass : autogain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
# ------ detection BlankClip and condition to avoid division by 0
blanklip = RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01) RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
#---- autogain process
r_gain = 1 - (1 - float(255.0/RCS_MinMaxDiff_0)) * autogain
r_bias = - RCS_Min_0 * r_gain * autogain
g_gain = 1 - (1 - float(255.0/RCS_MinMaxDiff_1)) * autogain
g_bias = - RCS_Min_1 * g_gain * autogain
b_gain = 1 - (1 - float(255.0/RCS_MinMaxDiff_2)) * autogain
b_bias = - RCS_Min_2 * b_gain * autogain
ref = (RCS_Ave_0 * r_gain + r_bias + RCS_Ave_1 * g_gain + g_bias + RCS_Ave_2 * b_gain + b_bias)/3
#---- autocont process
r_cont = 1 - (1 - r_gain) * autocont
r_cont_max = RCS_Max_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Max_0 - 128)
g_cont = 1 - (1 - g_gain) * autocont
g_cont_max = RCS_Max_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Max_1 - 128)
b_cont = 1 - (1 - b_gain) * autocont
b_cont_max = RCS_Max_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Max_2 - 128)
r_cont_bias = (255 - r_cont_max) * autocont
g_cont_bias = (255 - g_cont_max) * autocont
b_cont_bias = (255 - b_cont_max) * autocont
r_bias = r_bias + r_cont_bias
g_bias = g_bias + g_cont_bias
b_bias = b_bias + b_cont_bias
#---------- gamma curves and bias corrections process in accordance with gray world theory
#----------- RGB values calculation
r_gain_cont_ave = RCS_Ave_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Ave_0 - 128)
g_gain_cont_ave = RCS_Ave_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Ave_1 - 128)
b_gain_cont_ave = RCS_Ave_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Ave_2 - 128)
#----------- RGB corrections values calcul
# In gray world theory, in YUV range, ref = 128, but in RGB range average of channel average values
# is better, with average of channel average value after autogain process the picture ligth is better
dr = ref - r_gain_cont_ave # gray world theory bias correction calcul
dg = ref - g_gain_cont_ave
db = ref - b_gain_cont_ave
#----- RGB correction with Rpow curve calcul
r_rpow = 1 - (1 - pow(4.0,dr/128.0)) * rpow
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 - (1 - pow(4.0,dg/128.0)) * rpow
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 - (1 - pow(4.0,db/128.0)) * rpow
b_rpow = Min (4.0, Max (b_rpow, 0.1))
#----------- RGB correction with Spow curve calcul
#------- Spow process is enable in default mode, spmid and pord args default values increase
#------- rpow process action, thus we get more color saturation but also more dark aeras.
r_spow = 1 - (1 - 1/r_rpow) * spow
r_spow = Min (4.0, Max (r_spow, 0.1))
g_spow = 1 - (1 - 1/g_rpow) * spow
g_spow = Min (4.0, Max (g_spow, 0.1))
b_spow = 1 - (1 - 1/b_rpow) * spow
b_spow = Min (4.0, Max (b_spow, 0.1))
r_spmid = (rpow == 0 || spow == 0) ? 0.5 : r_gain_cont_ave/255.0
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = (rpow == 0 || spow == 0) ? 0.5 : g_gain_cont_ave/255.0
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = (rpow == 0 || spow == 0) ? 0.5 : b_gain_cont_ave/255.0
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#----------- RGB bias corrections calcul
r_bias = (r_bias + dr * bias)
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = (g_bias + dg * bias)
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = (b_bias + db * bias)
b_bias = Min (512.0, Max (b_bias, -512.0))
#------------ gain and cont in RGBadapt args range
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0))
g_cont = Min (8.0, Max (g_cont, -8.0))
b_cont = Min (8.0, Max (b_cont, -8.0))
RGBAdapt( RGB_clip, \
R_Bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_RPow = r_rpow, R_Spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,\
G_Bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_RPow = g_rpow, G_Spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,\
B_Bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_RPow = b_rpow, B_Spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
(blanklip == 0) ? RGB_clip : last
#----------- variables are tuned in global mode for data display in following ScriptClip
global r_bias = (!show_info)? nop : r_bias global g_bias = (!show_info)? nop : g_bias global b_bias = (!show_info)? nop : b_bias
global r_gain = (!show_info)? nop : r_gain global g_gain = (!show_info)? nop : g_gain global b_gain = (!show_info)? nop : b_gain
global r_cont = (!show_info)? nop : r_cont global g_cont = (!show_info)? nop : g_cont global b_cont = (!show_info)? nop : b_cont
global r_rpow = (!show_info)? nop : r_rpow global g_rpow = (!show_info)? nop : g_rpow global b_rpow = (!show_info)? nop : b_rpow
global r_spow = (!show_info)? nop : r_spow global g_spow = (!show_info)? nop : g_spow global b_spow = (!show_info)? nop : b_spow
global r_spmid = (!show_info)? nop : r_spmid global g_spmid = (!show_info)? nop : g_spmid global b_spmid = (!show_info)? nop : b_spmid
global pord = (!show_info)? nop : pord global ref = ref
return last """, args = "RGB_clip, matrix, show_info, x, y, w , h, autogain, threshold, autocont, rpow, spow, pord, bias")
#--------- datas display process
(!show_info) ? last :\
ScriptClip(last, """
#---------- First pass : autogain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
#----- extraction for gain/cont calculation and final display
r_Min = RCS_Min_0 g_min = RCS_Min_1 b_min = RCS_Min_2
r_Max = RCS_Max_0 g_max = RCS_Max_1 b_max = RCS_Max_2
r_MinmaxDiff = RCS_MinMaxDiff_0 g_minMaxDiff = RCS_MinMaxDiff_1 b_MinMaxDiff = RCS_MinMaxDiff_2
r_Ave = RCS_Ave_0 g_Ave = RCS_Ave_1 b_Ave = RCS_Ave_2
#--------- Final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
Subtitle("channels averages average : " + string((r_ave + g_ave + b_ave )/3)+\
"\n "+\
"\nRed values : "+\
"\nDeparture : " + " Average : " + String(r_Ave) + " Min/max : " + String(r_MinMaxDiff)\
+ " Min : " + String(r_Min)+ " Max : " + String(r_Max)+\
"\n R_bias : " + String(r_bias) + " R_gain : " + String(r_gain) + " R_cont : " + String(r_cont) +\
"\n R_rpow : " + String(r_rpow )+ " R_spow : " + String(r_spow) + " R_spmid : " + String(r_spmid)+\
"\nFinish : " + " Average : " + String(RCS_Ave_0) + " Min/max : " + String(RCS_MinMaxDiff_0)\
+ " Min : " + String(RCS_Min_0)+ " Max : " + String(RCS_Max_0)\
, y= float(height()/32.0), lsp= 20, text_color = $00FFFF00, halo_color = $00000000, size = float(height()/32.0))\
.Subtitle("Green values : "+\
"\nDeparture : "+ " Average : " + String(g_Ave) + " Min/max : " + String(g_MinMaxDiff)\
+ " Min : " + String(g_Min)+ " Max : " + String(g_Max)+\
"\n G_bias : " + String(g_bias) + " G_gain : " + String(g_gain) + " G_cont : " + String(g_cont)+\
"\n G_rpow : " + String(g_rpow) + " G_spow : " + String(g_spow) + " G_spmid : " + String(g_spmid) +\
"\nFinish : " + " Average : " + String(RCS_Ave_1) + " Min/max : " + String(RCS_MinMaxDiff_1)\
+ " Min : " + String(RCS_Min_1)+ " Max : " + String(RCS_Max_1)\
, y= 10 * float(height()/32.0), lsp= 20, text_color = $00FFFF00, halo_color = $00000000, size = float(height()/32.0))\
.Subtitle("Blue values : "+\
"\nDeparture : " + " Average : " + String(b_Ave) + " Min/max : " + String(b_MinMaxDiff)\
+ " Min : " + String(b_Min)+ " Max : " + String(b_Max)+\
"\n B_bias : " + String(b_bias) + " B_gain : " + String(b_gain)+ " B_cont : " + String(b_cont) +\
"\n B_rpow : " + String(b_rpow) + " B_spow : " + String(b_spow) + " B_spmid : " + String(b_spmid) +\
"\nFinish : " + " Average :" + String(RCS_Ave_2) + " Min/max : " + String(RCS_MinMaxDiff_2)\
+ " Min : " + String(RCS_Min_2)+ " Max : " + String(RCS_Max_2)+\
"\n "+\
"\nchannels averages average : " + string((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2 )/3)\
, y = 17 * float(height()/32.0), lsp = 20, text_color = $00FFFF00, halo_color = $00000000, size = float(height()/32.0))
return last """, args = "RGB_clip, matrix, show_info, x, y, w , h, threshold")
Bernardd
3rd October 2016, 19:24
The script function part II
#-------- display scrutinized aera
scrutinized_green = (!show_scrutinized)? nop : BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = (!show_scrutinized)? nop : Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = (!show_scrutinized)? nop : Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = (!show_scrutinized)? nop : Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = (!show_scrutinized)? nop : Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
(!show_scrutinized)? last : scrutinized
#--------- End of RGB color space process
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
}
And on YouTube scriptdemo on John Meyer's sample (http://forum.doom9.org/showthread.php?p=1780794#post1780794 )
https://youtu.be/9ewbXiM01uw
Bernard
Bernardd
5th October 2016, 11:38
Hello,
I apologize, i have a definition error in function call script. autogain, autocont, rpow, spow and bias are not bool but float. I have amended call script in post before this one.
Bernard
StainlessS
5th October 2016, 16:02
Yo Berni,
Subtitle("channels averages average : " + string((r_ave + g_ave + b_ave )/3)+\
"\n "+\
"\nRed values : "+\
"\nDeparture : " + " Average : " + String(r_Ave) + " Min/max : " + String(r_MinMaxDiff)\
+ " Min : " + String(r_Min)+ " Max : " + String(r_Max)+\
"\n R_bias : " + String(r_bias) + " R_gain : " + String(r_gain) + " R_cont : " + String(r_cont) +\
"\n R_rpow : " + String(r_rpow )+ " R_spow : " + String(r_spow) + " R_spmid : " + String(r_spmid)+\
"\nFinish : " + " Average : " + String(RCS_Ave_0) + " Min/max : " + String(RCS_MinMaxDiff_0)\
+ " Min : " + String(RCS_Min_0)+ " Max : " + String(RCS_Max_0)\
, y= float(height()/32.0), lsp= 20, text_color = $00FFFF00, halo_color = $00000000, size = float(height()/32.0))\
.Subtitle("Green values : "+\
"\nDeparture : "+ " Average : " + String(g_Ave) + " Min/max : " + String(g_MinMaxDiff)\
+ " Min : " + String(g_Min)+ " Max : " + String(g_Max)+\
"\n G_bias : " + String(g_bias) + " G_gain : " + String(g_gain) + " G_cont : " + String(g_cont)+\
"\n G_rpow : " + String(g_rpow) + " G_spow : " + String(g_spow) + " G_spmid : " + String(g_spmid) +\
"\nFinish : " + " Average : " + String(RCS_Ave_1) + " Min/max : " + String(RCS_MinMaxDiff_1)\
+ " Min : " + String(RCS_Min_1)+ " Max : " + String(RCS_Max_1)\
, y= 10 * float(height()/32.0), lsp= 20, text_color = $00FFFF00, halo_color = $00000000, size = float(height()/32.0))\
.Subtitle("Blue values : "+\
"\nDeparture : " + " Average : " + String(b_Ave) + " Min/max : " + String(b_MinMaxDiff)\
+ " Min : " + String(b_Min)+ " Max : " + String(b_Max)+\
"\n B_bias : " + String(b_bias) + " B_gain : " + String(b_gain)+ " B_cont : " + String(b_cont) +\
"\n B_rpow : " + String(b_rpow) + " B_spow : " + String(b_spow) + " B_spmid : " + String(b_spmid) +\
"\nFinish : " + " Average :" + String(RCS_Ave_2) + " Min/max : " + String(RCS_MinMaxDiff_2)\
+ " Min : " + String(RCS_Min_2)+ " Max : " + String(RCS_Max_2)+\
"\n "+\
"\nchannels averages average : " + string((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2 )/3)\
, y = 17 * float(height()/32.0), lsp = 20, text_color = $00FFFF00, halo_color = $00000000, size = float(height()/32.0))
You could probably make life a bit easier by using RT_String() instead of all of the String() functions and '+' string concatenations.
Subtitle is a little awkward in that it would need to use '\\n' rather than just '\n' because RT_String would convert '\n' in format string to
a Chr(10) [but Subtitle actually wants '\n' literally, '\\n' the double backslash is escaped to a single '\n' as Subtitle requires.
Alternatively, you could just use '\n' which would be turned into Chr(10), and then use eg RT_StrReplace(S, Chr(10),"\n") to finally convert
back to '\n' strings.
If 2nd method used, then could also send S to RT_DebugF(S) prior to doing the string replace, or to RT_Subtitle instead.
Standard string conversion and concatenation is real tedious in Avisynth.
Bernardd
6th October 2016, 09:03
Hello StainlessS,
Thanks for the tip. I look your write script proposal.
Bernard
Bernardd
25th October 2016, 23:12
Hi StainlessS
Below a new version of my script.
In gray world theory, we compute a bias for increasing or decreasing average values at 128.
By the same way, for gamma correction, i compute now a rpow for increasing or decreasing average values to 128.
128 = pow(average value/255, 1/rpow)*255, thus rpow = log(average value/255)/log(128/255).
With this new rpow, results are near GamMac results.
In my script i get better results with average of channels averages values than with 128.
The script have, like the oldest versions, the following args : gain, cont, rpow, spow, pord and bias tunable args, but also
two boolean args to enable or desable automatic weitghed strength for cont and spow. With these two automatic
weigthed args enable, the default args give often good results.
In the following posts are first the call script, with AvsPmod user sliders opportunity
and after the function script.
Bernard
PS : i have done a little use of RT_String
Bernardd
25th October 2016, 23:12
The call script
AVISource("C:\.............\your video.avi")
LoadPlugin("C:\.............\GRunT.dll")
LoadPlugin("C:\.............\RGBAdapt.dll")
LoadPlugin("C:\.............\RT_Stats26.dll")
# display tunings
comparison = false
show_scrutinized = false
show_info = false
# color space matrix tuning and specify the source rectangle under scrutiny
matrix = "Rec601"
x = 0.09
Y= 0.09
w = 0.09
h = 0.09
# autogain tunings
threshold = 0.10
gain_strength = 1.0
# autocontraste tunings
auto_cont = true
cont_strength = 1.0
# gamma process tunings
auto_spow = true
rpow_strength = 1.0
spow_strength = 1.0
pord = false
# bias tuning
bias_strength = 1.0
# If you use AvsPmod user sliders you can delete comment for follow lines
#~ [<separator="display tunings">]
#~ comparison = Select([<"show different settings - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_scrutinized = Select([<"show scrutinized aera - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_info = Select([<"show datas - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="color space matrix tuning - specify the source rectangle under scrutiny and percentage extreme pixels to ignore">]
#~ matrix = Select([<"color matrix - (Rec 601= 0 ou Rec 709 =1) = default = 0", 0, 1, 0>], "Rec601" , "Rec709")
#~ x = [<"ignore pixels on left - width percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ Y= [<"ignore pixels on top - heigth percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ w = [<"ignore pixels on right - width percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ h = [<"ignore pixels on bottom - heigth percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ threshold = [<"percentage for extreme pixels to be ignored - default : 0.10", 0.00, 1.00, 0.1>]
#~ [<separator="automatic white balance tunings">]
#~ [<separator="gain_strengthargs tunings">]
#~ gain_strength = [<"enable and strength gain process - default = 1.0", 0.0, 1.0, 1.0>]
#~ [<separator="cont_strength args tunings - - cont arg can be free or automatic tunable">]
#~ auto_cont = Select([<"auto_cont - (auto weighted cont_strength ) default = true = 1", 0, 1, 1>], false , true)
#~ [<separator="----------- below free or automatic strength adjust">]
#~ cont_strength = [<"----------- enable and strength cont process - default = 1.0", 0.0, 1.0, 1.0>]
#~ [<separator="gamma process args tunings - - spow args can be free or automatic tunable">]
#~ auto_spow = Select([<"auto_spow - (auto weighted spow_strength) default = true = 1", 0, 1, 1>], false , true)
#~ [<separator="----------- below free or automatic strength adjust">]
#~ rpow_strength = [<"----------- enable and strength rpow process - default = 1.0", 0.0, 1.0, 1.0>]
#~ spow_strength = [<"----------- enable and strength spow process - default = 1.0", 0.0, 1.0, 1.0>]
#~ pord = Select([<"----------- pord - (false = rpow before spow ) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="free bias_strength args tuning">]
#~ bias_strength = [<"enable and strength bias process - default = 1.0", 0.0, 1.0, 1.0>]
output = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold = threshold, gain_strength = gain_strength, auto_cont = auto_cont,cont_strength = cont_strength, \
auto_spow = auto_spow,rpow_strength = rpow_strength, spow_strength = spow_strength, pord = pord, bias_strength = bias_strength)
without_cont_output = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, cont_strength = 0.0, auto_spow = false)\
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain, rpow_strength, spow_strength and bias process no cont and no auto mode for gamma"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 1.0" + " auto_cont : false cont strength : 0.0" + \
"\n auto_spow : false rpow strength : 1.0" + " spow strength : 1.0" + " pord : false" +\
"\n bias strength : 1.0" , lsp = 20)
bias_only = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, gain_strength = 0.0, cont_strength = 0.0, rpow_strength = 0.0)\
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("bias process only output near ColorYUV autowhite"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 0.0" + " auto_cont : false cont strength : 0.0" + \
"\n auto_spow : false rpow strength : 0.0" + " spow strength : 0.0" + " pord : false" +\
"\n bias strength : 1.0" , lsp = 20)
gain_bias_only = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, cont_strength = 0.0, rpow_strength = 0.0)\
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain and bias process only"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 1.0" + " auto_cont : false cont strength : 0.0" + \
"\n auto_spow : false rpow strength : 0.0" + " spow strength : 0.0" + " pord : false" +\
"\n bias strength : 1.0", lsp = 20)
gain_gamma_only = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, cont_strength = 0.0, auto_spow = false, bias_strength = 0.0) \
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain cont rpow and spow process but no bias process and no auto mode for cont and gamma"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 1.0" + " auto_cont : false cont strength : 0.0" + \
"\n auto_spow : false rpow strength : 1.0" + " spow strength : 1.0" + " pord : false" +\
"\n bias strength : 0.0" , lsp = 20)
all = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, threshold = threshold) \
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain cont rpow spow and bias process with auto mode for cont and gamma"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 1.0" + " auto_cont : true cont strength : 1.0" + \
"\n auto_spow : true rpow strength : 1.0" + " spow strength : 1.0" + " pord : false" +\
"\n bias strength : 1.0" , lsp = 20)
compared_output = (!comparison) ? nop : StackVertical(StackHorizontal(last.AddBorders(0, 80, 0, 0, color=$000000).Subtitle("original"),gain_bias_only, all), \
StackHorizontal(bias_only, gain_gamma_only, output .AddBorders(0, 80, 0, 0, color=$000000)\
. Subtitle ("user setting where all args are free" + \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : " + LeftStr(string(gain_strength),3) + " auto_cont : " + string(auto_cont)+\
" cont strength : " + LeftStr(string(cont_strength),3) + \
"\n auto_spow : " + string(auto_spow) + " rpow strength : " + LeftStr(string(rpow_strength),3) +" spow strength : " + \
LeftStr(string(spow_strength),3) + " pord : " + string(pord) +\
"\n bias strength : " + LeftStr(string(bias_strength),3) , lsp = 20)))
(!comparison) ? output : compared_output
Bernardd
25th October 2016, 23:15
The function script part 1
# ---------------------------- function script -------------------------------------
function RGBAdapt_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
float "threshold", float "gain_strength" , bool "auto_cont", float "cont_strength", \
bool "auto_spow", float "rpow_strength", float "spow_strength", bool "pord", float "bias_strength")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1584313#post1584313 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
Assert(IsYV12(clip) || IsRGB(clip)," Input video colorspace must be YV12 or RGB, not YUV")
matrix = string(Default(matrix, "Rec601") ) # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
show_scrutinized = Default(show_scrutinized, false) # show scrutinized aera or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.00)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(x>=0.00 && x <= 0.99,"RGBAdapt_auto_awb: x 0.00 -> 0.99")
y = float(Default(y,0.00)) #heignt percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(y>=0.00 && y <= 0.99,"RGBAdapt_auto_awb: y 0.00 -> 0.99")
w = float(Default(w,0.00)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(w>=0.00 && w <= 0.99,"RGBAdapt_auto_awb: w 0.00 -> 0.99")
Assert(x+w>=0.00 && x+w <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
h = float(Default(h,0.00)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(h>=0.00 && h <= 0.99,"RGBAdapt_auto_awb: h 0.00 -> 0.99")
Assert(y+h>=0.00 && y+h <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.00 -> 1.00")
gain_strength = Float(Default(gain_strength, 1.00)) # strength arg for gain
Assert(gain_strength>=0.00 && gain_strength <= 1.00,"RGBAdapt_auto_awb: gain_strength 0.00 -> 1.00")
auto_cont = Default(auto_cont, true) # auto weighted cont_strength arg
cont_strength = Float(Default(cont_strength, 1.00)) # strength arg for contrast
Assert(cont_strength>=0.00 && cont_strength <= 1.00,"RGBAdapt_auto_awb: cont_strength 0.00 -> 1.00")
auto_spow = Default(auto_spow, true) # auto weighted rpow_strength arg control by cont_strength arg
rpow_strength = Float(Default(rpow_strength, 1.00)) # strength arg for rpow
Assert(rpow_strength>=0.00 && rpow_strength <= 1.00,"RGBAdapt_auto_awb: rpow_strength 0.00 -> 1.00")
spow_strength = Float(Default(spow_strength, 1.00)) # strength arg for spow
Assert(spow_strength>=0.00 && spow_strength <= 1.00,"RGBAdapt_auto_awb: spow_strength 0.00 -> 1.00")
pord = Default(pord, false) # RGBAdapt pord arg
bias_strength = Float(Default(bias_strength, 1.00)) # strength arg for automatic bias_strength
Assert(bias_strength>=0.00 && bias_strength <= 1.00,"RGBAdapt_auto_awb: bias_strength 0.00 -> 1.00")
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#--------- RGB color space process
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#--------- AWB process
ScriptClip(RGB_clip, """
#---------- First pass : gain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
# ------ detection BlankClip and condition to avoid division by 0
blanklip = RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01) RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
#---- gain process
r_gain = 1 - (1 - float(255.0/RCS_MinMaxDiff_0)) * gain_strength
r_bias = - RCS_Min_0 * r_gain * gain_strength
g_gain = 1 - (1 - float(255.0/RCS_MinMaxDiff_1)) * gain_strength
g_bias = - RCS_Min_1 * g_gain * gain_strength
b_gain = 1 - (1 - float(255.0/RCS_MinMaxDiff_2)) * gain_strength
b_bias = - RCS_Min_2 * b_gain * gain_strength
#---- cont process
# Cont is dangerous, because it can overshoot light and dark, but it is necessary to help to find good correction for very big
# color cast. Thus bool auto_cont arg enable a automatic weighted autocont stength. I observe that picture do'nt need contraste is
# picture, which have a large histogram, which have min value near 0 et max value near 255, which have bigger min max diff value.
# But not it is simple, sometime the automatic weigthed autocont stength must be desable.
r_cont = (!auto_cont) ? 1 - (1 - r_gain) * cont_strength : 1 - (1 - r_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
r_cont_max = RCS_Max_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Max_0 - 128)
g_cont = (!auto_cont) ? 1 - (1 - g_gain) * cont_strength : 1 - (1 - g_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
g_cont_max = RCS_Max_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Max_1 - 128)
b_cont = (!auto_cont) ? 1 - (1 - b_gain) * cont_strength : 1 - (1 - b_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
b_cont_max = RCS_Max_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Max_2 - 128)
r_cont_bias = (!auto_cont) ? (255 - r_cont_max) * cont_strength : \
(255 - r_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
g_cont_bias = (!auto_cont) ? (255 - g_cont_max) * cont_strength : \
(255 - g_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
b_cont_bias = (!auto_cont) ? (255 - b_cont_max) * cont_strength : \
(255 - b_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
#------------ gain and cont in RGBadapt args range
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0))
g_cont = Min (8.0, Max (g_cont, -8.0))
b_cont = Min (8.0, Max (b_cont, -8.0))
r_bias = r_bias + r_cont_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = g_bias + g_cont_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = b_bias + b_cont_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
#---------- gamma curves corrections process in accordance with gray world theory
#----------- RGB values calculation
r_gain_cont_ave = RCS_Ave_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Ave_0 - 128)
g_gain_cont_ave = RCS_Ave_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Ave_1 - 128)
b_gain_cont_ave = RCS_Ave_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Ave_2 - 128)
#----------- RGB gamma corrections values calcul
# In gray world theory, in YUV range, we increase or decrease average value to ref = 128.0, but in RGB range
# average of channel average values is better, with average of channel average value after gain process the
# picture ligth is better
# In gamma process, to incresae or decrease average value, we use gamma args. To find this gamma args, we
# solve this equation ref = pow(average value/255.0,1/gamma args)
# Gamma corrections are calculated with gain output, because is more refine than calculated with gain and cont output
ref = (RCS_Ave_0 * r_gain + r_bias + RCS_Ave_1 * g_gain + g_bias + RCS_Ave_2 * b_gain + b_bias)/3.0
r_rpow = 1 + (log((RCS_Ave_0 * r_gain + r_bias)/255.0)/log(ref/255.0) -1) * rpow_strength
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 + (log((RCS_Ave_1* g_gain + g_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 + (log((RCS_Ave_2 * b_gain + b_bias)/255.0)/log(ref/255.0) -1) * rpow_strength
b_rpow = Min (4.0, Max (b_rpow, 0.1))
#----------- RGB correction with spow curve calcul
#------- Spow process is enable in default mode, spmid and pord args default values increase
#------- rpow process action, thus we get more color saturation but also more dark aeras.
#------- Spow for rpow is like contrast for gain. Thus i use the same factor to get automatic
#------- weigthed spow arg
r_spow = (!auto_spow) ? 1 - (1 - 1/r_rpow) * spow_strength : \
1 - (1 - 1/r_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
r_spow = Min (4.0, Max (r_spow, 0.1))
g_spow = (!auto_spow) ? 1 - (1 - 1/g_rpow) * spow_strength : \
1 - (1 - 1/g_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
g_spow = Min (4.0, Max (g_spow, 0.1))
b_spow = (!auto_spow) ? 1 - (1 - 1/b_rpow) * spow_strength : \
1 - (1 - 1/b_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
b_spow = Min (4.0, Max (b_spow, 0.1))
r_spmid = (r_spow == 1.0) ? 0.5 : (RCS_Ave_0 * r_gain + r_bias)/255.0
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = (g_spow == 1.0) ? 0.5 : (RCS_Ave_1* g_gain + g_bias)/255.0
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = (b_spow == 1.0) ? 0.5 : (RCS_Ave_2 * b_gain + b_bias)/255.0
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#---------- bias corrections process in accordance with gray world theory
#----------- RGB bias corrections extraction and calcul
RGBAdapt( RGB_clip, \
R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
RT_RgbChanStats( LAST, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
ref = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3.0 # in RGB range ref is better 128.0 for Gray world theory correction
dr = ref - RCS_Ave_0
dg = ref - RCS_Ave_1
db = ref - RCS_Ave_2
r_bias = (r_bias + dr * bias_strength)
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = (g_bias + dg * bias_strength)
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = (b_bias + db * bias_strength)
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip, \
R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
(blanklip == 0) ? RGB_clip : last
#----------- variables strings are tuned in global mode for data display in following ScriptClip
global r_args = (!show_info)? nop : \
RT_String("\\n R_bias : %s R_gain : %s R_cont : %s \\n R_rpow : %s R_spow : %s R_spmid : %s",\
string(r_bias), string(r_gain), string(r_cont), string(r_rpow), string(r_spow), string(r_spmid),esc =1)
global g_args = (!show_info)? nop : \
RT_String("\\n G_bias : %s G_gain : %s G_cont : %s \\n G_rpow : %s G_spow : %s G_spmid : %s",\
string(g_bias), string(g_gain), string(g_cont), string(g_rpow), string(g_spow), string(g_spmid),esc =1)
global b_args = (!show_info)? nop : \
RT_String("\\n B_bias : %s B_gain : %s B_cont : %s \\n B_rpow : %s B_spow : %s B_spmid : %s",\
string(b_bias), string(b_gain), string(b_cont), string(b_rpow), string(b_spow), string(b_spmid),esc =1)
return last """, args = "RGB_clip, show_info, x, y, w , h, gain_strength, threshold, auto_cont, cont_strength, auto_spow, rpow_strength, spow_strength,"+\
"pord, bias_strength")
Bernardd
25th October 2016, 23:16
The function script part 2
#--------- datas display process
(!show_info) ? last :\
ScriptClip(last, """
#--------- start RGB values extraction for display
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
start_ave = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3.0
r_start = RT_String("\\nDeparture : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_0), string(RCS_MinMaxDiff_0), string(RCS_Min_0), string(RCS_Max_0),esc =1)
g_start = RT_String("\\nDeparture : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_1), string(RCS_MinMaxDiff_1), string(RCS_Min_1), string(RCS_Max_1),esc =1)
b_start = RT_String("\\nDeparture : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_2), string(RCS_MinMaxDiff_2), string(RCS_Min_2), string(RCS_Max_2),esc =1)
#--------- final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
r_end = RT_String("\\nFinish : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_0), string(RCS_MinMaxDiff_0), string(RCS_Min_0), string(RCS_Max_0),esc =1)
g_end = RT_String("\\nFinish : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_1), string(RCS_MinMaxDiff_1), string(RCS_Min_1), string(RCS_Max_1),esc =1)
b_end = RT_String("\\nFinish : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_2), string(RCS_MinMaxDiff_2), string(RCS_Min_2), string(RCS_Max_2),esc =1)
#-------- display
Subtitle("channels averages average : " + string(start_ave)+\
"\n\n" + "Red values : " + r_start + r_args + r_end +\
"\n\n" + "Green values : " + g_start + g_args + g_end+\
"\n\n" + "Blue values : " + b_start + b_args + b_end+\
"\n\n" + "channels averages average : " + string((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2 )/3)\
,y = 20, lsp = 20, text_color = $00FFFF00, halo_color = $00000000, size = float(height()/32.0))
return last """, args = "RGB_clip, x, y, w , h, threshold")
#-------- display scrutinized aera
scrutinized_green = (!show_scrutinized)? nop : BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = (!show_scrutinized)? nop : Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = (!show_scrutinized)? nop : Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = (!show_scrutinized)? nop : Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = (!show_scrutinized)? nop : Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
(!show_scrutinized)? last : scrutinized
#--------- End of RGB color space process
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
}
StainlessS
25th October 2016, 23:24
Nice job Bernardd,
Just a second suggestion (by all means ignore), but RT_Subtitle is way faster than regular subtitle and with built in formatting
just like RT_String. Probably not of any great concern if static Subtitle applied on full clip, but if using eg ScriptClip to apply
some changing text/metrics, then would be significantly faster. Align arg also works as in Avisynth standard Subtitle, but has 1 or two
extra args I think (also works in color, but not large text, see demo in RT_ AVS/FSel_&_Subtitle_Demo/).
fvisagie
26th October 2016, 05:01
Nice job Bernardd,
Just a second suggestion (by all means ignore), but RT_Subtitle is way faster than regular subtitle and with built in formatting
just like RT_String. Probably not of any great concern if static Subtitle applied on full clip, but if using eg ScriptClip to apply
some changing text/metrics, then would be significantly faster. Align arg also works as in Avisynth standard Subtitle, but has 1 or two
extra args I think (also works in color, but not large text, see demo in RT_ AVS/FSel_&_Subtitle_Demo/).
Further advantages of RT_Subtitle() are that it supports all AVS colourspaces, and uses less memory especially on longer files (when called from ScriptClip() at least).
Bernardd
26th October 2016, 23:42
Hi StainlessS
In following posts, new version of the script, only function script no the unchanged call script.
The changes are in the end :
the best "ref" for final bias process, i take anymore the average of channels averages values of last extraction,
but the average of channels averages values given by gain process.
a try of use RT_Subtitle. It is not perfect, because today i cannot find how adjust letter size. With SD material the text
finish out of the screen. have you a tips ? Perhaps i must change order of displayed datas.
Thanks
The function script part 1
# ---------------------------- function script -------------------------------------
function RGBAdapt_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
float "threshold", float "gain_strength" , bool "auto_cont", float "cont_strength", \
bool "auto_spow", float "rpow_strength", float "spow_strength", bool "pord", float "bias_strength")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1681286#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?p=1584313#post1584313 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.php?p=1157083#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
Assert(IsYV12(clip) || IsRGB(clip)," Input video colorspace must be YV12 or RGB, not YUV")
matrix = string(Default(matrix, "Rec601") ) # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709", """RGBAdapt_auto_awb: matrix "Rec601" or "Rec709"""")
show_scrutinized = Default(show_scrutinized, false) # show scrutinized aera or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.00)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(x>=0.00 && x <= 0.99,"RGBAdapt_auto_awb: x 0.00 -> 0.99")
y = float(Default(y,0.00)) #heignt percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(y>=0.00 && y <= 0.99,"RGBAdapt_auto_awb: y 0.00 -> 0.99")
w = float(Default(w,0.00)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(w>=0.00 && w <= 0.99,"RGBAdapt_auto_awb: w 0.00 -> 0.99")
Assert(x+w>=0.00 && x+w <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
h = float(Default(h,0.00)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(h>=0.00 && h <= 0.99,"RGBAdapt_auto_awb: h 0.00 -> 0.99")
Assert(y+h>=0.00 && y+h <= 0.99 ,"RGBAdapt_auto_awb: x+w 0.00 -> 0.99")
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(threshold>=0.00 && threshold <= 1.00,"RGBAdapt_auto_awb: threshold 0.00 -> 1.00")
gain_strength = Float(Default(gain_strength, 1.00)) # strength arg for gain
Assert(gain_strength>=0.00 && gain_strength <= 1.00,"RGBAdapt_auto_awb: gain_strength 0.00 -> 1.00")
auto_cont = Default(auto_cont, true) # auto weighted cont_strength arg
cont_strength = Float(Default(cont_strength, 1.00)) # strength arg for contrast
Assert(cont_strength>=0.00 && cont_strength <= 1.00,"RGBAdapt_auto_awb: cont_strength 0.00 -> 1.00")
auto_spow = Default(auto_spow, true) # auto weighted rpow_strength arg control by cont_strength arg
rpow_strength = Float(Default(rpow_strength, 1.00)) # strength arg for rpow
Assert(rpow_strength>=0.00 && rpow_strength <= 1.00,"RGBAdapt_auto_awb: rpow_strength 0.00 -> 1.00")
spow_strength = Float(Default(spow_strength, 1.00)) # strength arg for spow
Assert(spow_strength>=0.00 && spow_strength <= 1.00,"RGBAdapt_auto_awb: spow_strength 0.00 -> 1.00")
pord = Default(pord, false) # RGBAdapt pord arg
bias_strength = Float(Default(bias_strength, 1.00)) # strength arg for automatic bias_strength
Assert(bias_strength>=0.00 && bias_strength <= 1.00,"RGBAdapt_auto_awb: bias_strength 0.00 -> 1.00")
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#--------- RGB color space process
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#--------- AWB process
ScriptClip(RGB_clip, """
#---------- First pass : gain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
# ------ detection BlankClip and condition to avoid division by 0
blanklip = RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01) RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
#---- gain process
r_gain = 1 - (1 - float(255.0/RCS_MinMaxDiff_0)) * gain_strength
r_bias = - RCS_Min_0 * r_gain * gain_strength
g_gain = 1 - (1 - float(255.0/RCS_MinMaxDiff_1)) * gain_strength
g_bias = - RCS_Min_1 * g_gain * gain_strength
b_gain = 1 - (1 - float(255.0/RCS_MinMaxDiff_2)) * gain_strength
b_bias = - RCS_Min_2 * b_gain * gain_strength
#---- cont process
# Cont is dangerous, because it can overshoot light and dark, but it is necessary to help to find good correction for very big
# color cast. Thus bool auto_cont arg enable a automatic weighted autocont stength. I observe that picture do'nt need contraste is
# picture, which have a large histogram, which have min value near 0 et max value near 255, which have bigger min max diff value.
# But not it is simple, sometime the automatic weigthed autocont stength must be desable.
r_cont = (!auto_cont) ? 1 - (1 - r_gain) * cont_strength : 1 - (1 - r_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
r_cont_max = RCS_Max_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Max_0 - 128)
g_cont = (!auto_cont) ? 1 - (1 - g_gain) * cont_strength : 1 - (1 - g_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
g_cont_max = RCS_Max_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Max_1 - 128)
b_cont = (!auto_cont) ? 1 - (1 - b_gain) * cont_strength : 1 - (1 - b_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
b_cont_max = RCS_Max_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Max_2 - 128)
r_cont_bias = (!auto_cont) ? (255 - r_cont_max) * cont_strength : \
(255 - r_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
g_cont_bias = (!auto_cont) ? (255 - g_cont_max) * cont_strength : \
(255 - g_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
b_cont_bias = (!auto_cont) ? (255 - b_cont_max) * cont_strength : \
(255 - b_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
#------------ gain and cont in RGBadapt args range
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0))
g_cont = Min (8.0, Max (g_cont, -8.0))
b_cont = Min (8.0, Max (b_cont, -8.0))
r_bias = r_bias + r_cont_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = g_bias + g_cont_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = b_bias + b_cont_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
#---------- gamma curves corrections process in accordance with gray world theory
#----------- RGB values calculation
r_gain_cont_ave = RCS_Ave_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Ave_0 - 128)
g_gain_cont_ave = RCS_Ave_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Ave_1 - 128)
b_gain_cont_ave = RCS_Ave_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Ave_2 - 128)
#----------- RGB gamma corrections values calcul
# In gray world theory, in YUV range, we increase or decrease average value to ref = 128.0, but in RGB range
# average of channel average values is better, with average of channel average value after gain process the
# picture ligth is better
# In gamma process, to incresae or decrease average value, we use gamma args. To find this gamma args, we
# solve this equation ref = pow(average value/255.0,1/gamma args)
# Gamma corrections are calculated with gain output, because is more refine than calculated with gain and cont output
ref = (RCS_Ave_0 * r_gain + r_bias + RCS_Ave_1 * g_gain + g_bias + RCS_Ave_2 * b_gain + b_bias)/3.0
r_rpow = 1 + (log((RCS_Ave_0 * r_gain + r_bias)/255.0)/log(ref/255.0) -1) * rpow_strength
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 + (log((RCS_Ave_1* g_gain + g_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 + (log((RCS_Ave_2 * b_gain + b_bias)/255.0)/log(ref/255.0) -1) * rpow_strength
b_rpow = Min (4.0, Max (b_rpow, 0.1))
#----------- RGB correction with spow curve calcul
#------- Spow process is enable in default mode, spmid and pord args default values increase
#------- rpow process action, thus we get more color saturation but also more dark aeras.
#------- Spow for rpow is like contrast for gain. Thus i use the same factor to get automatic
#------- weigthed spow arg
r_spow = (!auto_spow) ? 1 - (1 - 1/r_rpow) * spow_strength : \
1 - (1 - 1/r_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
r_spow = Min (4.0, Max (r_spow, 0.1))
g_spow = (!auto_spow) ? 1 - (1 - 1/g_rpow) * spow_strength : \
1 - (1 - 1/g_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
g_spow = Min (4.0, Max (g_spow, 0.1))
b_spow = (!auto_spow) ? 1 - (1 - 1/b_rpow) * spow_strength : \
1 - (1 - 1/b_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
b_spow = Min (4.0, Max (b_spow, 0.1))
r_spmid = (r_spow == 1.0) ? 0.5 : (RCS_Ave_0 * r_gain + r_bias)/255.0
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = (g_spow == 1.0) ? 0.5 : (RCS_Ave_1* g_gain + g_bias)/255.0
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = (b_spow == 1.0) ? 0.5 : (RCS_Ave_2 * b_gain + b_bias)/255.0
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#---------- bias corrections process in accordance with gray world theory
#----------- RGB bias corrections extraction and calcul
RGBAdapt( RGB_clip, \
R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
RT_RgbChanStats( LAST, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
dr = ref - RCS_Ave_0 # better result with average of average values given by gain process
dg = ref - RCS_Ave_1
db = ref - RCS_Ave_2
r_bias = (r_bias + dr * bias_strength)
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = (g_bias + dg * bias_strength)
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = (b_bias + db * bias_strength)
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip, \
R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
(blanklip == 0) ? RGB_clip : last
#----------- variables strings are tuned in global mode for data display in following ScriptClip
global r_args1 = (!show_info)? nop : \
RT_String("\\n R_bias : %s R_gain : %s R_cont : %s \\n R_rpow : %s R_spow : %s R_spmid : %s",\
string(r_bias), string(r_gain), string(r_cont), string(r_rpow), string(r_spow), string(r_spmid),esc =1)
global g_args1 = (!show_info)? nop : \
RT_String("\\n G_bias : %s G_gain : %s G_cont : %s \\n G_rpow : %s G_spow : %s G_spmid : %s",\
string(g_bias), string(g_gain), string(g_cont), string(g_rpow), string(g_spow), string(g_spmid),esc =1)
global b_args1 = (!show_info)? nop : \
RT_String("\\n B_bias : %s B_gain : %s B_cont : %s \\n B_rpow : %s B_spow : %s B_spmid : %s",\
string(b_bias), string(b_gain), string(b_cont), string(b_rpow), string(b_spow), string(b_spmid),esc =1)
return last """, args = "RGB_clip, show_info, x, y, w , h, gain_strength, threshold, auto_cont, cont_strength, auto_spow, rpow_strength, spow_strength,"+\
"pord, bias_strength")
Bernard
Bernardd
26th October 2016, 23:44
The function script part 2
#--------- datas display process
(!show_info) ? last :\
ScriptClip(last, """
#--------- start RGB values extraction for display
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
start_ave = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3.0
r_start1 = RT_String("\\nDeparture : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_0), string(RCS_MinMaxDiff_0), string(RCS_Min_0), string(RCS_Max_0),esc =1)
g_start1 = RT_String("\\nDeparture : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_1), string(RCS_MinMaxDiff_1), string(RCS_Min_1), string(RCS_Max_1),esc =1)
b_start1 = RT_String("\\nDeparture : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_2), string(RCS_MinMaxDiff_2), string(RCS_Min_2), string(RCS_Max_2),esc =1)
#--------- final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
r_end1 = RT_String("\\nFinish : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_0), string(RCS_MinMaxDiff_0), string(RCS_Min_0), string(RCS_Max_0),esc =1)
g_end1 = RT_String("\\nFinish : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_1), string(RCS_MinMaxDiff_1), string(RCS_Min_1), string(RCS_Max_1),esc =1)
b_end1 = RT_String("\\nFinish : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_2), string(RCS_MinMaxDiff_2), string(RCS_Min_2), string(RCS_Max_2),esc =1)
#-------- display
RT_Subtitle("channels averages average : %s
\nRed value : %s %s %s
\nGreen values : %s %s %s
\nBlue values : %s %s %s
\nchannels averages average : %s",\
string(start_ave), r_start1, r_args1, r_end1, g_start1, g_args1, g_end1, b_start1, b_args1, b_end1,\
string((RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2 )/3),y = 20, esc = 2)
return last """, args = "RGB_clip, x, y, w , h, threshold")
#-------- display scrutinized aera
scrutinized_green = (!show_scrutinized)? nop : BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = (!show_scrutinized)? nop : Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = (!show_scrutinized)? nop : Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = (!show_scrutinized)? nop : Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = (!show_scrutinized)? nop : Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
(!show_scrutinized)? last : scrutinized
#--------- End of RGB color space process
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
}
StainlessS
27th October 2016, 09:12
Bernardd, made a few mods, use as you will.
Added RT_String to Asserts.
Removed String from "String(Default(matrix, "Rec601"))", not necessary.
Changed eg "x>=0.00 && x <= 0.99" to "0.0 <= x <= 0.99" see http://forum.doom9.org/showthread.php?p=1783132#post1783132
Removed 'Float', eg (255.0/1) always float result. eg r_gain = 1 - (1 - (255.0/RCS_MinMaxDiff_0) * gain_strength
Converted RT_String "%s" string args to float "%f" (RT_String does conversion) eg
From:-
b_start1 = RT_String("\\nDeparture : Average : %s Min/max : %s Min : %s Max : %s",\
string(RCS_Ave_2), string(RCS_MinMaxDiff_2), string(RCS_Min_2), string(RCS_Max_2),esc =1)
To:-
b_start1 = RT_String("\\nDeparture : Average : %f Min/max : %f Min : %f Max : %f", RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2,esc =1)
Added Global r_args2, etc.
Mod of Subtitle Stuff. (use RT_Subtitle if frame big enough, else use Subtitle).
part1
# ---------------------------- function script -------------------------------------
function RGBAdapt_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
float "threshold", float "gain_strength" , bool "auto_cont", float "cont_strength", \
bool "auto_spow", float "rpow_strength", float "spow_strength", bool "pord", float "bias_strength")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.ph...86#post1681286 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.ph...13#post1584313 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# script author : Gavino http://forum.doom9.org/showthread.ph...83#post1157083 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
myName="RGBAdapt_awb_process: "
Assert(IsYV12(clip) || IsRGB(clip),RT_String("%sInput video colorspace must be YV12 or RGB, not YUV",myName))
matrix = Default(matrix, "Rec601") # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709",RT_String("%smatrix 'Rec601' or 'Rec709'('%s')",myName,matrix))
show_scrutinized = Default(show_scrutinized, false) # show scrutinized area or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.0)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= x <= 0.99,RT_String("%s0.0 <= x <= 0.99(%f)",myName,x))
y = float(Default(y,0.0)) #height percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= y <= 0.99,RT_String("%s0.0 <= y <= 0.99(%f)",myName,y))
w = float(Default(w,0.0)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= w <= 0.99,RT_String("%s0.0 <= w <= 0.99(%f)",myName,w))
Assert(0.0 <= (x+w) <= 0.99 ,RT_String("%s0.0 <= (x+w) <= 0.99(%f)",myName,x+w))
h = float(Default(h,0.0)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= h <= 0.99,RT_String("%s0.0 <= h <= 0.99(%f)",myName,h))
Assert(0.0 <= (y+h) <= 0.99 ,RT_String("%s0.0 <= (y+h) <= 0.99(%f)",myName,y+h))
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(0.0 <= threshold <= 1.0,RT_String("%s0.0 <= threshold <= 1.0(%f)",myName,threshold))
gain_strength = Float(Default(gain_strength, 1.0)) # strength arg for gain
Assert(0.0 <= gain_strength <= 1.0,RT_String("%s0.0 <= gain_strength <= 1.0(%f)",myName,gain_strength))
auto_cont = Default(auto_cont, true) # auto weighted cont_strength arg
cont_strength = Float(Default(cont_strength, 1.0)) # strength arg for contrast
Assert(0.0 <= cont_strength <= 1.0,RT_String("%s0.0 <= cont_strength <= 1.0(%f)",myName,cont_strength))
auto_spow = Default(auto_spow, true) # auto weighted rpow_strength arg control by cont_strength arg
rpow_strength = Float(Default(rpow_strength, 1.0)) # strength arg for rpow
Assert(0.0 <= rpow_strength <= 1.0,RT_String("%s0.0 <= rpow_strength <= 1.0(%f)",myName,rpow_strength))
spow_strength = Float(Default(spow_strength, 1.0)) # strength arg for spow
Assert(0.0 <= spow_strength <= 1.0,RT_String("%s0.0 <= spow_strength <= 1.0(%f)",myName,spow_strength))
pord = Default(pord, false) # RGBAdapt pord arg
bias_strength = Float(Default(bias_strength, 1.0)) # strength arg for automatic bias_strength
Assert(0.0 <= bias_strength <= 1.0,RT_String("%s0.0 <= bias_strength <= 1.0(%f)",myName,bias_strength))
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#--------- RGB color space process
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#--------- AWB process
ScriptClip(RGB_clip, """
#---------- First pass : gain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
# ------ detection BlankClip and condition to avoid division by 0
blanklip = RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01) RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
#---- gain process
r_gain = 1 - (1 - (255.0/RCS_MinMaxDiff_0)) * gain_strength
r_bias = - RCS_Min_0 * r_gain * gain_strength
g_gain = 1 - (1 - (255.0/RCS_MinMaxDiff_1)) * gain_strength
g_bias = - RCS_Min_1 * g_gain * gain_strength
b_gain = 1 - (1 - (255.0/RCS_MinMaxDiff_2)) * gain_strength
b_bias = - RCS_Min_2 * b_gain * gain_strength
#---- cont process
# Cont is dangerous, because it can overshoot light and dark, but it is necessary to help to find good correction for very big
# color cast. Thus bool auto_cont arg enable a automatic weighted autocont stength. I observe that picture do'nt need contraste is
# picture, which have a large histogram, which have min value near 0 et max value near 255, which have bigger min max diff value.
# But not it is simple, sometime the automatic weigthed autocont stength must be desable.
r_cont = (!auto_cont) ? 1 - (1 - r_gain) * cont_strength : 1 - (1 - r_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
r_cont_max = RCS_Max_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Max_0 - 128)
g_cont = (!auto_cont) ? 1 - (1 - g_gain) * cont_strength : 1 - (1 - g_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
g_cont_max = RCS_Max_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Max_1 - 128)
b_cont = (!auto_cont) ? 1 - (1 - b_gain) * cont_strength : 1 - (1 - b_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
b_cont_max = RCS_Max_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Max_2 - 128)
r_cont_bias = (!auto_cont) ? (255 - r_cont_max) * cont_strength : \
(255 - r_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
g_cont_bias = (!auto_cont) ? (255 - g_cont_max) * cont_strength : \
(255 - g_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
b_cont_bias = (!auto_cont) ? (255 - b_cont_max) * cont_strength : \
(255 - b_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
#------------ gain and cont in RGBadapt args range
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0))
g_cont = Min (8.0, Max (g_cont, -8.0))
b_cont = Min (8.0, Max (b_cont, -8.0))
r_bias = r_bias + r_cont_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = g_bias + g_cont_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = b_bias + b_cont_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
#---------- gamma curves corrections process in accordance with gray world theory
#----------- RGB values calculation
r_gain_cont_ave = RCS_Ave_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Ave_0 - 128)
g_gain_cont_ave = RCS_Ave_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Ave_1 - 128)
b_gain_cont_ave = RCS_Ave_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Ave_2 - 128)
#----------- RGB gamma corrections values calcul
# In gray world theory, in YUV range, we increase or decrease average value to ref = 128.0, but in RGB range
# average of channel average values is better, with average of channel average value after gain process the
# picture light is better
# In gamma process, to incresae or decrease average value, we use gamma args. To find this gamma args, we
# solve this equation ref = pow(average value/255.0,1/gamma args)
# Gamma corrections are calculated with gain output, because is more refine than calculated with gain and cont output
ref = (RCS_Ave_0 * r_gain + r_bias + RCS_Ave_1 * g_gain + g_bias + RCS_Ave_2 * b_gain + b_bias)/3.0
r_rpow = 1 + (log((RCS_Ave_0 * r_gain + r_bias)/255.0)/log(ref/255.0) -1) * rpow_strength
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 + (log((RCS_Ave_1* g_gain + g_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 + (log((RCS_Ave_2 * b_gain + b_bias)/255.0)/log(ref/255.0) -1) * rpow_strength
b_rpow = Min (4.0, Max (b_rpow, 0.1))
#----------- RGB correction with spow curve calcul
#------- Spow process is enable in default mode, spmid and pord args default values increase
#------- rpow process action, thus we get more color saturation but also more dark aeras.
#------- Spow for rpow is like contrast for gain. Thus i use the same factor to get automatic
#------- weigthed spow arg
r_spow = (!auto_spow) ? 1 - (1 - 1/r_rpow) * spow_strength : \
1 - (1 - 1/r_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
r_spow = Min (4.0, Max (r_spow, 0.1))
g_spow = (!auto_spow) ? 1 - (1 - 1/g_rpow) * spow_strength : \
1 - (1 - 1/g_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
g_spow = Min (4.0, Max (g_spow, 0.1))
b_spow = (!auto_spow) ? 1 - (1 - 1/b_rpow) * spow_strength : \
1 - (1 - 1/b_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
b_spow = Min (4.0, Max (b_spow, 0.1))
r_spmid = (r_spow == 1.0) ? 0.5 : (RCS_Ave_0 * r_gain + r_bias)/255.0
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = (g_spow == 1.0) ? 0.5 : (RCS_Ave_1* g_gain + g_bias)/255.0
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = (b_spow == 1.0) ? 0.5 : (RCS_Ave_2 * b_gain + b_bias)/255.0
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#---------- bias corrections process in accordance with gray world theory
#----------- RGB bias corrections extraction and calcul
RGBAdapt( RGB_clip, \
R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
RT_RgbChanStats( LAST, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
dr = ref - RCS_Ave_0 # better result with average of average values given by gain process
dg = ref - RCS_Ave_1
db = ref - RCS_Ave_2
r_bias = (r_bias + dr * bias_strength)
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = (g_bias + dg * bias_strength)
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = (b_bias + db * bias_strength)
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip, \
R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
(blanklip == 0) ? RGB_clip : last
#----------- variables strings are tuned in global mode for data display in following ScriptClip
global r_args1 = (!show_info)? nop : RT_String(" R_bias=%7.3f : R_gain=%7.3f : R_cont =%7.3f",r_bias, r_gain, r_cont)
global r_args2 = (!show_info)? nop : RT_String(" R_rpow=%7.3f : R_spow=%7.3f : R_spmid=%7.3f",r_rpow,r_spow,r_spmid)
global g_args1 = (!show_info)? nop : RT_String(" G_bias=%7.3f : G_gain=%7.3f : G_cont =%7.3f",g_bias, g_gain, g_cont)
global g_args2 = (!show_info)? nop : RT_String(" G_rpow=%7.3f : G_spow=%7.3f : G_spmid=%7.3f",g_rpow, g_spow, g_spmid)
global b_args1 = (!show_info)? nop : RT_String(" B_bias=%7.3f : B_gain=%7.3f : B_cont =%7.3f",b_bias, b_gain, b_cont)
global b_args2 = (!show_info)? nop : RT_String(" B_rpow=%7.3f : B_spow=%7.3f : B_spmid=%7.3f",b_rpow, b_spow, b_spmid)
return last """, args = "RGB_clip, show_info, x, y, w , h, gain_strength, threshold, auto_cont, cont_strength, auto_spow, rpow_strength, spow_strength,"+\
"pord, bias_strength")
StainlessS
27th October 2016, 09:13
part 2
###########
###########
###########
#--------- datas display process
(!show_info) ? last :\
ScriptClip(last, """
#--------- start RGB values extraction for display
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
start_ave = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3.0
r_start1 = RT_String("Departure : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d",RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0)
g_start1 = RT_String("Departure : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d",RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1)
b_start1 = RT_String("Departure : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d",RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2)
#--------- final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
r_end1 = RT_String("Finish : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d", RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0)
g_end1 = RT_String("Finish : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d", RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1)
b_end1 = RT_String("Finish : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d", RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2)
#-------- display
CWID=65 CHIT=25 # display Width and Height in Subtitle characters
MinWid=CWID*10 MinHit=CHIT*20 # RT_Subtitle required width height in pixels (fixed font size is 10x20)
TooSmall=(Width<MinWid || Height<MinHit)
S=RT_String("\nchannels averages average : %f\n" +
\ "Red values :\n" +
\ "%s\n%s\n%s\n%s\n\n" +
\ "Green values :\n" +
\ "%s\n%s\n%s\n%s\n\n" +
\ "Blue values :\n" +
\ "%s\n%s\n%s\n%s\n\n" +
\ "channels averages average : %f",
\ start_ave,
\ r_start1, r_args1, r_args2, r_end1,
\ g_start1, g_args1, g_args2, g_end1,
\ b_start1, b_args1, g_args2, b_end1,
\ (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2 )/3,Esc=(TooSmall)?0:1)
(TooSmall)
\ ? Subtitle(S,Font="Courier New",lsp=0,text_color=$00FFFF00,halo_color=$00000000,size=height/float(CHIT),Font_width=width/FloaT(CWID))
\ : RT_Subtitle("%s",S)
return last """, args = "RGB_clip, x, y, w , h, threshold")
###########
###########
###########
#-------- display scrutinized aera
scrutinized_green = (!show_scrutinized)? nop : BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = (!show_scrutinized)? nop : Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = (!show_scrutinized)? nop : Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = (!show_scrutinized)? nop : Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = (!show_scrutinized)? nop : Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
(!show_scrutinized)? last : scrutinized
#--------- End of RGB color space process
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
}
Will use RT_Subtitle if frame big enough, else switch to SubTitle(used MonoSpaced font "Courier New") and font size will adjust to frame size.
EDIT: By the way, lsp adjusts EXTRA spacing for font, nearly always set as lsp=0.
Bernardd
27th October 2016, 09:49
Thanks StainlessS
First, I adopt your change. The script run always well and it is better for datas display.
Second, it is a pleasure to learn from one code writter master.
Bernard
StainlessS
27th October 2016, 10:02
Bernard
Average=%-7.3f : Min/max=%-3d
Formats 1st '%-7.3f' (float) arg to 7 characters (minimum) and left aligned ('-') with 3 character precision for fractional part.
'%-3d' format 3 character minimum for int args, left aligned ('%03d' would print eg '001' non significant zeros are printed)
Also eg '%1s', "True" would print only 1 character of string "True" ie "T".
Really powerful formatting options, see the Micro$oft link in docs for full info on formatting options (you can even supply eg precision as a data arg).
EDIT: eg "%-7.*f",4,PI would print "3.1416s" (* used for precision as data arg [where s is space]).
EDIT: Above in blue edited, was "3.146ss", oops.
EDIT: Changed this line (increased both by 1, avoid rounding error on small frames [font size can be a little too large @ eg 320x240]).
CWID=65 CHIT=25 # display Width and Height in Subtitle characters
StainlessS
27th October 2016, 14:05
Bernardd, another mod, use as you will.
Made multi-instance capable (but in the process managed to get rid of global variables, but now can use GScript If/Else etc).
/*
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=170642 #
#------------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need RT_Stats plugin ----------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=165479 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=139337 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
#---------------------------------------------- need GScript plugin ----------------------------------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=147846 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
*/
Function RGBAdapt_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h",
\ float "threshold", float "gain_strength" , bool "auto_cont", float "cont_strength",
\ bool "auto_spow", float "rpow_strength", float "spow_strength", bool "pord", float "bias_strength") {
clip
myName="RGBAdapt_awb_process: "
Assert(RT_FunctionExist("RGBAdapt"),myName+"Essential RGBAdapt plugin installed, http://forum.doom9.org/showthread.php?t=170642")
Assert(RT_FunctionExist("GScriptClip"),myName+"Essential GRunT plugin installed, http://forum.doom9.org/showthread.php?t=139337")
Assert(RT_FunctionExist("GScript"),myName+"Essential GScript plugin installed, http://forum.doom9.org/showthread.php?t=147846")
Assert(IsYV12() || IsRGB(),RT_String("%sInput video colorspace must be YV12 or RGB, not YUV",myName))
matrix = Default(matrix, "Rec601") # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709",RT_String("%smatrix 'Rec601' or 'Rec709'('%s')",myName,matrix))
show_scrutinized = Default(show_scrutinized, false) # show scrutinized area or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.0)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= x <= 0.99,RT_String("%s0.0 <= x <= 0.99(%f)",myName,x))
y = float(Default(y,0.0)) #height percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= y <= 0.99,RT_String("%s0.0 <= y <= 0.99(%f)",myName,y))
w = float(Default(w,0.0)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= w <= 0.99,RT_String("%s0.0 <= w <= 0.99(%f)",myName,w))
Assert(0.0 <= (x+w) <= 0.99 ,RT_String("%s0.0 <= (x+w) <= 0.99(%f)",myName,x+w))
h = float(Default(h,0.0)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= h <= 0.99,RT_String("%s0.0 <= h <= 0.99(%f)",myName,h))
Assert(0.0 <= (y+h) <= 0.99 ,RT_String("%s0.0 <= (y+h) <= 0.99(%f)",myName,y+h))
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(0.0 <= threshold <= 1.0,RT_String("%s0.0 <= threshold <= 1.0(%f)",myName,threshold))
gain_strength = Float(Default(gain_strength, 1.0)) # strength arg for gain
Assert(0.0 <= gain_strength <= 1.0,RT_String("%s0.0 <= gain_strength <= 1.0(%f)",myName,gain_strength))
auto_cont = Default(auto_cont, true) # auto weighted cont_strength arg
cont_strength = Float(Default(cont_strength, 1.0)) # strength arg for contrast
Assert(0.0 <= cont_strength <= 1.0,RT_String("%s0.0 <= cont_strength <= 1.0(%f)",myName,cont_strength))
auto_spow = Default(auto_spow, true) # auto weighted rpow_strength arg control by cont_strength arg
rpow_strength = Float(Default(rpow_strength, 1.0)) # strength arg for rpow
Assert(0.0 <= rpow_strength <= 1.0,RT_String("%s0.0 <= rpow_strength <= 1.0(%f)",myName,rpow_strength))
spow_strength = Float(Default(spow_strength, 1.0)) # strength arg for spow
Assert(0.0 <= spow_strength <= 1.0,RT_String("%s0.0 <= spow_strength <= 1.0(%f)",myName,spow_strength))
pord = Default(pord, false) # RGBAdapt pord arg
bias_strength = Float(Default(bias_strength, 1.0)) # strength arg for automatic bias_strength
Assert(0.0 <= bias_strength <= 1.0,RT_String("%s0.0 <= bias_strength <= 1.0(%f)",myName,bias_strength))
# ---------------------------- function script -------------------------------------
#---------- Specify the source rectangle under scrutiny
x = int(Width() * x)
y = int(Height() * y)
w = int(-Width() * w)
h = int(-Height() * h)
#--------- RGB color space process
(!isRGB()) ? ConvertToRGB24(matrix=matrix) : NOP
# Use same string at each frame.
Fmt=
\ "\nchannels averages average : %f\n\n" +
\ "Red values :\n" +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n"+
\ " R_bias=%7.3f : R_gain =%7.3f : R_cont =%.3f\n"+
\ " R_rpow=%7.3f : R_spow =%7.3f : R_spmid=%.3f\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "\nGreen values :\n" +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n"+
\ " G_bias=%7.3f : G_gain =%7.3f : G_cont =%.3f\n"+
\ " G_rpow=%7.3f : G_spow =%7.3f : G_spmid=%.3f\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "\nBlue values :\n" +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n"+
\ " B_bias=%7.3f : B_gain =%7.3f : B_cont =%.3f\n"+
\ " B_rpow=%7.3f : B_spow =%7.3f : B_spmid=%.3f\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "\nchannels averages average : %f"
CWID=70 CHIT=23 # display Width and Height in Subtitle characters
MinWid=CWID*10 MinHit=CHIT*20 # RT_Subtitle required width height in pixels (fixed font size is 10x20)
TooSmall=(Width<MinWid || Height<MinHit)
#--------- AWB process
# ssS, NOTE, Args x,y,w,h to RGBAdapt_awb_process_Lo are Type Int
GSCript("""
Function RGBAdapt_awb_process_Lo(clip clp,bool show_info, int x, int y, int w, int h,
\ float threshold, float gain_strength , bool auto_cont, float cont_strength,
\ bool auto_spow, float rpow_strength, float spow_strength, bool pord, float bias_strength,String Fmt,Bool TooSmall,Int CWid,Int CHit) {
clp
n = current_frame # We dont actually use n for anything, I'll leave it here, maybe want to access eg n-1, ie RT_RgbChanStats(n=n-1)
#---------- First pass : gain process for each channel
Last.RT_RgbChanStats(x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
# ssS, Leave RCS_ values as original (avoid repeat function call in Show_info), new variables without RCS_ prefix, avoid divide by zero
MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01)
MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01)
MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
#---- gain process
r_gain = 1 - (1 - (255.0/MinMaxDiff_0)) * gain_strength
r_bias = - RCS_Min_0 * r_gain * gain_strength
g_gain = 1 - (1 - (255.0/MinMaxDiff_1)) * gain_strength
g_bias = - RCS_Min_1 * g_gain * gain_strength
b_gain = 1 - (1 - (255.0/MinMaxDiff_2)) * gain_strength
b_bias = - RCS_Min_2 * b_gain * gain_strength
#---- cont process
# Cont is dangerous, because it can overshoot light and dark, but it is necessary to help to find good correction for very big
# color cast. Thus bool auto_cont arg enable a automatic weighted autocont stength. I observe that picture do'nt need contraste is
# picture, which have a large histogram, which have min value near 0 et max value near 255, which have bigger min max diff value.
# But not it is simple, sometime the automatic weigthed autocont stength must be desable.
r_cont = (!auto_cont) ? 1 - (1 - r_gain) * cont_strength : 1 - (1 - r_gain) * cont_strength * (255.0 - MinMaxDiff_0)/255.0
r_cont_max = RCS_Max_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Max_0 - 128)
g_cont = (!auto_cont) ? 1 - (1 - g_gain) * cont_strength : 1 - (1 - g_gain) * cont_strength * (255.0 - MinMaxDiff_1)/255.0
g_cont_max = RCS_Max_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Max_1 - 128)
b_cont = (!auto_cont) ? 1 - (1 - b_gain) * cont_strength : 1 - (1 - b_gain) * cont_strength * (255.0 - MinMaxDiff_2)/255.0
b_cont_max = RCS_Max_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Max_2 - 128)
r_cont_bias = (!auto_cont) ? (255 - r_cont_max) * cont_strength : (255 - r_cont_max) * cont_strength * (255.0 - MinMaxDiff_0)/255.0
g_cont_bias = (!auto_cont) ? (255 - g_cont_max) * cont_strength : (255 - g_cont_max) * cont_strength * (255.0 - MinMaxDiff_1)/255.0
b_cont_bias = (!auto_cont) ? (255 - b_cont_max) * cont_strength : (255 - b_cont_max) * cont_strength * (255.0 - MinMaxDiff_2)/255.0
EDIT: Your plugin links were broken, fixed.
EDIT: Updated, removed unnecessary multi-instance stuff, still multi-instance capable (no Globals)
StainlessS
27th October 2016, 14:06
Part 2
#------------ gain and cont in RGBadapt args range
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0))
g_cont = Min (8.0, Max (g_cont, -8.0))
b_cont = Min (8.0, Max (b_cont, -8.0))
r_bias = r_bias + r_cont_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = g_bias + g_cont_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = b_bias + b_cont_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
#---------- gamma curves corrections process in accordance with gray world theory
#----------- RGB values calculation
r_gain_cont_ave = RCS_Ave_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Ave_0 - 128)
g_gain_cont_ave = RCS_Ave_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Ave_1 - 128)
b_gain_cont_ave = RCS_Ave_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Ave_2 - 128)
#----------- RGB gamma corrections values calcul
# In gray world theory, in YUV range, we increase or decrease average value to ref = 128.0, but in RGB range
# average of channel average values is better, with average of channel average value after gain process the
# picture light is better
# In gamma process, to incresae or decrease average value, we use gamma args. To find this gamma args, we
# solve this equation ref = pow(average value/255.0,1/gamma args)
# Gamma corrections are calculated with gain output, because is more refine than calculated with gain and cont output
ref = (RCS_Ave_0 * r_gain + r_bias + RCS_Ave_1 * g_gain + g_bias + RCS_Ave_2 * b_gain + b_bias)/3.0
r_rpow = 1 + (log((RCS_Ave_0 * r_gain + r_bias)/255.0)/log(ref/255.0) -1) * rpow_strength
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 + (log((RCS_Ave_1* g_gain + g_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 + (log((RCS_Ave_2 * b_gain + b_bias)/255.0)/log(ref/255.0) -1) * rpow_strength
b_rpow = Min (4.0, Max (b_rpow, 0.1))
#----------- RGB correction with spow curve calcul
#------- Spow process is enable in default mode, spmid and pord args default values increase
#------- rpow process action, thus we get more color saturation but also more dark aeras.
#------- Spow for rpow is like contrast for gain. Thus i use the same factor to get automatic
#------- weigthed spow arg
r_spow = (!auto_spow) ? 1 - (1 - 1/r_rpow) * spow_strength : 1 - (1 - 1/r_rpow) * spow_strength * (255.0 - MinMaxDiff_0)/255.0
r_spow = Min (4.0, Max (r_spow, 0.1))
g_spow = (!auto_spow) ? 1 - (1 - 1/g_rpow) * spow_strength : 1 - (1 - 1/g_rpow) * spow_strength * (255.0 - MinMaxDiff_1)/255.0
g_spow = Min (4.0, Max (g_spow, 0.1))
b_spow = (!auto_spow) ? 1 - (1 - 1/b_rpow) * spow_strength : 1 - (1 - 1/b_rpow) * spow_strength * (255.0 - MinMaxDiff_2)/255.0
b_spow = Min (4.0, Max (b_spow, 0.1))
r_spmid = (r_spow == 1.0) ? 0.5 : (RCS_Ave_0 * r_gain + r_bias)/255.0
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = (g_spow == 1.0) ? 0.5 : (RCS_Ave_1* g_gain + g_bias)/255.0
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = (b_spow == 1.0) ? 0.5 : (RCS_Ave_2 * b_gain + b_bias)/255.0
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#---------- bias corrections process in accordance with gray world theory
#----------- RGB bias corrections extraction and calcul
# ssS, Create and measure temp clip
TempC=Last.RGBAdapt(
\ R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,
\ G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,
\ B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
TempC.RT_RgbChanStats(x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16,Prefix="TMP_")
dr = ref - TMP_Ave_0 # better result with average of average values given by gain process
dg = ref - TMP_Ave_1
db = ref - TMP_Ave_2
r_bias = (r_bias + dr * bias_strength)
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = (g_bias + dg * bias_strength)
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = (b_bias + db * bias_strength)
b_bias = Min (512.0, Max (b_bias, -512.0))
# ssS, now change for real
Last.RGBAdapt(
\ R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,
\ G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,
\ B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
if(show_info) {
#--------- final RGB values extraction for display
# ssS, Used different Prefix so as not to destroy original variables
Last.RT_RgbChanStats(x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16,Prefix="FIN_")
#-------- display
S=RT_String(Fmt,
\ (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3.0,
\
\ RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0,
\ r_bias, r_gain,r_cont,
\ r_rpow,r_spow,r_spmid,
\ FIN_Ave_0, FIN_MinMaxDiff_0, FIN_Min_0, FIN_Max_0,
\
\ RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1,
\ g_bias, g_gain,g_cont,
\ g_rpow,g_spow,g_spmid,
\ FIN_Ave_1, FIN_MinMaxDiff_1, FIN_Min_1, FIN_Max_1,
\
\ RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2,
\ b_bias,b_gain,b_cont,
\ b_rpow,b_spow,b_spmid,
\ FIN_Ave_2, FIN_MinMaxDiff_2, FIN_Min_2, FIN_Max_2,
\
\ (FIN_Ave_0 + FIN_Ave_1 + FIN_Ave_2 )/3,Esc=(TooSmall)?0:1)
(TooSmall)
\ ? Last.Subtitle(S,Font="Courier New",lsp=0,text_color=$00FFFF00,halo_color=$00000000,size=height/float(CHIT),Font_width=width/FloaT(CWID))
\ : Last.RT_Subtitle("%s",S)
} # end ShowInfo
Return Last
}
ARGS="show_info,x,y,w,h,threshold,gain_strength,auto_cont,cont_strength," +
\ "auto_spow,rpow_strength,spow_strength,pord,bias_strength,Fmt,TooSmall,CWid,CHit"
Last.GScriptClip("RGBAdapt_awb_process_Lo(last, "+ARGS+")", local=true, args=ARGS)
# ssS, Do border outside of Scriptclip.
if(show_scrutinized) {
#-------- display scrutinized area
scrutinized_green = Last.BlankClip(width = Last.Width-x+w, height = Last.Height-y+h, color=$00FF00)
scrutinized_white = scrutinized_green.Blankclip(color=$FFFFFF)
scrutinized_int = Last.Blankclip(width = scrutinized_white.Width-4, height = scrutinized_white.Height-4,color=000000)
scrutinized_mask = scrutinized_white.Overlay(scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,
\ ignore_conditional=false, pc_range=false)
Last.Overlay(scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,
\ ignore_conditional=false, pc_range=false)
} # End show_scrutinized
Return Last
""")
Return (!isRGB) ? ConvertToYV12(last, matrix=matrix) : last
}
Bernardd
27th October 2016, 21:34
Thanks StainlessS
With your explanations an tips, i discover a new world. I shall study these new ways.
Bernard
Bernardd
7th November 2016, 19:03
Hello StainlessS,
To day, i have not kept your multi-instance capable amend, because i search now a easier use for the script. Thus i have worked only on user's inputs.
My auto white balance script has many parameters.
To help with the choice of combinations of these parameters, I introduced a "preset" mode
This new preset parameter can take the values:
3, default value, corresponding to the use of the gain, contrast weighted, rpow, spow weighted and bias
2, only gain, rpow and unweighted spow
1, only gain and bias
0, no presets, all parameters are freely adjustable
To help in the selection of presets, the comparison shows now 9 versions of Clip
top, from left to right
the original, gain and only rpow process, combination of gain, contrast, rpow, spow and bias without contrast weighting and without spow weighting
in the middle, from left to right
gain and bias, combination of gain rpow and unweighted spow, combination of gain, contrast, rpow, spow and bias with contrast weighting and with spow weighting
bottom, from left to right
bias only, combination of gain rpow and weighted spow, and last combination given by the operator settings
To facilitate comparison, the preset outputs are all aligned in the middle. This presentation is to assess the action of the contrast and weights
by comparing with the output displayed at the top or bottom. Note that all the combinations are not displayed, but I hope that this provision helps
find the most effective combination.
Three examples of this comparison. The images are from the John Meyer's demo clip
Perhaps preset 1
http://img.xooimage.com/files110/f/4/9/john-homme_2-50d7b8e.png
Perhaps the preset 2
http://img.xooimage.com/files110/3/b/4/john-sable_2-50d7b9e.png
Perhaps the preset 3
http://img.xooimage.com/files110/f/3/8/john-perroquet_2-50d7bb7.png
The script is in the following posts
Bernard
Bernardd
7th November 2016, 19:23
The call script
AVISource("C:\.............\your video.avi")
LoadPlugin("C:\.............\GRunT.dll")
LoadPlugin("C:\.............\RGBAdapt.dll")
LoadPlugin("C:\.............\RT_Stats26.dll")
# display tunings
comparison = true
show_scrutinized = true
show_info = false
# color space matrix tuning and specify the source rectangle under scrutiny
matrix = "Rec601"
x = 0.09
Y= 0.09
w = 0.09
h = 0.09
preset = 3
# autogain tunings
threshold = 0.10
gain_strength = 1.0
# autocontraste tunings
auto_cont = true
cont_strength = 1.0
# gamma process tunings
auto_spow = true
rpow_strength = 1.0
spow_strength = 1.0
pord = false
# bias tuning
bias_strength = 1.0
# If you use AvsPmod user sliders you can delete comment for follow lines
#~ [<separator="display tunings">]
#~ comparison = Select([<"show different settings - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_scrutinized = Select([<"show scrutinized aera - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_info = Select([<"show datas - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="color space matrix tuning - specify the source rectangle under scrutiny and percentage extreme pixels to ignore">]
#~ matrix = Select([<"color matrix - (Rec 601= 0 ou Rec 709 =1) = default = 0", 0, 1, 0>], "Rec601" , "Rec709")
#~ x = [<"ignore pixels on left - width percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ Y= [<"ignore pixels on top - heigth percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ w = [<"ignore pixels on right - width percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ h = [<"ignore pixels on bottom - heigth percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ threshold = [<"percentage for extreme pixels to be ignored - default : 0.10", 0.00, 1.00, 0.1>]
#~ [<separator="automatic white balance tunings">]
#~ [<separator="------------ first automatic white balance tunings with preset 1 - 2 or 3">]
#~ preset = Select([<"preset (free - gain+bias - gain+rpow+spow or all) default = 3", 0, 3, 3>], 0 , 1, 2, 3)
#~ [<separator="------------ second automatic white balance tunings with free args when preset 0">]
#~ [<separator="gain_strength args tunings">]
#~ gain_strength = [<"enable and strength gain process - default = 1.0", 0.0, 1.0, 1.0>]
#~ [<separator="cont strength args tunings - - cont arg can be free or automatic weighted tunable">]
#~ auto_cont = Select([<"auto_cont - (auto weighted cont strength ) default = true = 1", 0, 1, 1>], false , true)
#~ [<separator="----------- below free or automatic weighted strength adjust">]
#~ cont_strength = [<"----------- enable and strength cont process - default = 1.0", 0.0, 1.0, 1.0>]
#~ [<separator="gamma process args tunings">]
#~ rpow_strength = [<"enable and strength rpow process - default = 1.0", 0.0, 1.0, 1.0>]
#~ [<separator="----------- spow args can be free or automatic weighted tunable">]
#~ auto_spow = Select([<"----------- auto_spow - (auto weighted spow strength) default = true = 1", 0, 1, 1>], false , true)
#~ spow_strength = [<"----------- enable and strength spow process - default = 1.0", 0.0, 1.0, 1.0>]
#~ pord = Select([<"pord - (false = rpow before spow ) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="free bias_strength args tuning">]
#~ bias_strength = [<"enable and strength bias process - default = 1.0", 0.0, 1.0, 1.0>]
output = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold = threshold, preset = preset, gain_strength = gain_strength, auto_cont = auto_cont,cont_strength = cont_strength, \
auto_spow = auto_spow,rpow_strength = rpow_strength, spow_strength = spow_strength, pord = pord, bias_strength = bias_strength)
bias_only = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, gain_strength = 0.0, cont_strength = 0.0, rpow_strength = 0.0, preset = 0)\
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("bias process only output near ColorYUV autowhite"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 0.0" + " auto_cont : true cont strength : 0.0" + \
"\n rpow strength : 0.0" + " auto_spow : true spow strength : 0.0" + " pord : false" +\
"\n bias strength : 1.0" , lsp = 20)
gain_bias_only = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, cont_strength = 0.0, rpow_strength = 0.0, preset = 1)\
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain and bias process only"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 1.0" + " auto_cont : true cont strength : 0.0" + \
"\n rpow strength : 0.0" + " auto_spow : true spow strength : 0.0" + " pord : false" +\
"\n bias strength : 1.0 preset 1", lsp = 20)
gain_rpow_only = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, cont_strength = 0.0, spow_strength = 0.0, bias_strength = 0.0, preset = 0) \
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain rpow process but no cont, no spow and no bias process"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 1.0" + " auto_cont : true cont strength : 0.0" + \
"\n rpow strength : 1.0" + " auto_spow : true spow strength : 0.0" + " pord : false" +\
"\n bias strength : 0.0" , lsp = 20)
gain_rpow_spow_only = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, cont_strength = 0.0, auto_spow = true, bias_strength = 0.0, preset = 0) \
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain rpow and auto weighted spow process but no cont and no bias process"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 1.0" + " auto_cont : false cont strength : 0.0" + \
"\n rpow strength : 1.0" + " auto_spow : true spow strength : 0.0" + " pord : false" +\
"\n bias strength : 0.0" , lsp = 20)
gain_rpow_spow_only_without_auto = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, \
threshold = threshold, cont_strength = 0.0, auto_cont = false, auto_spow = false, bias_strength = 0.0, preset = 2) \
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain, rpow and spow process but no cont and no bias process and no auto weighted mode for spow"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 1.0" + " auto_cont : false cont strength : 0.0" + \
"\n rpow strength : 1.0" + " auto_spow : false spow strength : 1.0" + " pord : false" +\
"\n bias strength : 0.0 preset 2" , lsp = 20)
all = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, threshold = threshold)\
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain cont rpow spow and bias process with auto mode for cont and gamma"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 1.0" + " auto_cont : true cont strength : 1.0" + \
"\n rpow strength : 1.0" + " auto_spow : true spow strength : 1.0" + " pord : false" +\
"\n bias strength : 1.0 preset 3" , lsp = 20)
all_without_auto = (!comparison) ? nop : RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = false, x = x, y = y, w = w, h = h, threshold = threshold,\
auto_cont = false, auto_spow = false, preset = 0) \
.AddBorders(0, 80, 0, 0, color=$000000). Subtitle ("gain cont rpow spow and bias process with auto mode for cont and gamma"+ \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : 1.0" + " auto_cont : false cont strength : 1.0" + \
"\n rpow strength : 1.0" + " auto_spow : false spow strength : 1.0" + " pord : false" +\
"\n bias strength : 1.0" , lsp = 20)
compared_output = (!comparison) ? nop : StackVertical(StackHorizontal(last.AddBorders(0, 80, 0, 0, color=$000000).Subtitle("original"),gain_rpow_only, all_without_auto), \
StackHorizontal(gain_bias_only,gain_rpow_spow_only_without_auto, all), \
StackHorizontal(bias_only, gain_rpow_spow_only, output .AddBorders(0, 80, 0, 0, color=$008000)\
. Subtitle ("user setting where all args are free and or preset number : " +string(preset) + \
"\n threshold : " + LeftStr(string(threshold),4) + " gain strength : " + LeftStr(string(gain_strength),3) + " auto_cont : " + string(auto_cont)+\
" cont strength : " + LeftStr(string(cont_strength),3) + \
"\n rpow strength : " + LeftStr(string(rpow_strength),3) +" auto_spow : " + string(auto_spow) + " spow strength : " + \
LeftStr(string(spow_strength),3) + " pord : " + string(pord) +\
"\n bias strength : " + LeftStr(string(bias_strength),3) , lsp = 20)))
(!comparison) ? output : compared_output
Bernardd
7th November 2016, 19:24
The function script part 1
# ---------------------------- function script -------------------------------------
function RGBAdapt_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
float "threshold", int "preset", float "gain_strength" , bool "auto_cont", float "cont_strength", \
bool "auto_spow", float "rpow_strength", float "spow_strength", bool "pord", float "bias_strength")
{
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=170642 #
#------------------------------------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need RT_Stats plugin -------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=165479 #
#------------------------------------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=139337 #
#-----------------------------------------------------------------------------------------------------------------------------------------------#
myName="RGBAdapt_awb_process: "
Assert(IsYV12(clip) || IsRGB(clip),RT_String("%sInput video colorspace must be YV12 or RGB, not YUV",myName))
matrix = Default(matrix, "Rec601") # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709",RT_String("%smatrix 'Rec601' or 'Rec709'('%s')",myName,matrix))
show_scrutinized = Default(show_scrutinized, false) # show scrutinized area or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.0)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= x <= 0.99,RT_String("%s0.0 <= x <= 0.99(%f)",myName,x))
y = float(Default(y,0.0)) #height percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= y <= 0.99,RT_String("%s0.0 <= y <= 0.99(%f)",myName,y))
w = float(Default(w,0.0)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= w <= 0.99,RT_String("%s0.0 <= w <= 0.99(%f)",myName,w))
Assert(0.0 <= (x+w) <= 0.99 ,RT_String("%s0.0 <= (x+w) <= 0.99(%f)",myName,x+w))
h = float(Default(h,0.0)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= h <= 0.99,RT_String("%s0.0 <= h <= 0.99(%f)",myName,h))
Assert(0.0 <= (y+h) <= 0.99 ,RT_String("%s0.0 <= (y+h) <= 0.99(%f)",myName,y+h))
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(0.0 <= threshold <= 1.0,RT_String("%s0.0 <= threshold <= 1.0(%f)",myName,threshold))
gain_strength = Float(Default(gain_strength, 1.0)) # strength arg for gain
Assert(0.0 <= gain_strength <= 1.0,RT_String("%s0.0 <= gain_strength <= 1.0(%f)",myName,gain_strength))
auto_cont = Default(auto_cont, true) # auto weighted cont_strength arg
cont_strength = Float(Default(cont_strength, 1.0)) # strength arg for contrast
Assert(0.0 <= cont_strength <= 1.0,RT_String("%s0.0 <= cont_strength <= 1.0(%f)",myName,cont_strength))
auto_spow = Default(auto_spow, true) # auto weighted rpow_strength arg control by cont_strength arg
rpow_strength = Float(Default(rpow_strength, 1.0)) # strength arg for rpow
Assert(0.0 <= rpow_strength <= 1.0,RT_String("%s0.0 <= rpow_strength <= 1.0(%f)",myName,rpow_strength))
spow_strength = Float(Default(spow_strength, 1.0)) # strength arg for spow
Assert(0.0 <= spow_strength <= 1.0,RT_String("%s0.0 <= spow_strength <= 1.0(%f)",myName,spow_strength))
pord = Default(pord, false) # RGBAdapt pord arg
bias_strength = Float(Default(bias_strength, 1.0)) # strength arg for automatic bias_strength
Assert(0.0 <= bias_strength <= 1.0,RT_String("%s0.0 <= bias_strength <= 1.0(%f)",myName,bias_strength))
preset= Int(Default(preset, 3))
Assert(0 <= preset <= 3,RT_String("%s preset = 0,1, 2 or 3 ( no %d)",myName,preset))
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#--------- RGB color space process
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#--------- AWB process
ScriptClip(RGB_clip, """
#---------- First pass : gain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
# ------ detection BlankClip and condition to avoid division by 0
blanklip = RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01) RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
#---- gain process
gain_strength = (preset == 1) || (preset == 2) || (preset == 3) ? 1.0 : gain_strength
r_gain = 1 - (1 - (255.0/RCS_MinMaxDiff_0)) * gain_strength
r_bias = - RCS_Min_0 * r_gain * gain_strength
g_gain = 1 - (1 - (255.0/RCS_MinMaxDiff_1)) * gain_strength
g_bias = - RCS_Min_1 * g_gain * gain_strength
b_gain = 1 - (1 - (255.0/RCS_MinMaxDiff_2)) * gain_strength
b_bias = - RCS_Min_2 * b_gain * gain_strength
#---- cont process
# Cont is dangerous, because it can overshoot light and dark, but it is necessary to help to find good correction for very big
# color cast. Thus bool auto_cont arg enable a automatic weighted autocont stength. I observe that picture do'nt need contraste is
# picture, which have a large histogram, which have min value near 0 et max value near 255, which have bigger min max diff value.
# But not it is simple, sometime the automatic weigthed autocont stength must be desable.
cont_strength = (preset == 1) || (preset == 2) ? 0.0 : ((preset == 3) ? 1.0 : cont_strength)
auto_cont = (preset == 1) || (preset == 2) || (preset == 3) ? true : auto_cont
r_cont = (!auto_cont) ? 1 - (1 - r_gain) * cont_strength : 1 - (1 - r_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
r_cont_max = RCS_Max_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Max_0 - 128)
g_cont = (!auto_cont) ? 1 - (1 - g_gain) * cont_strength : 1 - (1 - g_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
g_cont_max = RCS_Max_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Max_1 - 128)
b_cont = (!auto_cont) ? 1 - (1 - b_gain) * cont_strength : 1 - (1 - b_gain) * cont_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
b_cont_max = RCS_Max_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Max_2 - 128)
r_cont_bias = (!auto_cont) ? (255 - r_cont_max) * cont_strength : \
(255 - r_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
g_cont_bias = (!auto_cont) ? (255 - g_cont_max) * cont_strength : \
(255 - g_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
b_cont_bias = (!auto_cont) ? (255 - b_cont_max) * cont_strength : \
(255 - b_cont_max) * cont_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
#------------ gain and cont in RGBadapt args range
r_gain = Min (8.0, Max (r_gain, -8.0))
g_gain = Min (8.0, Max (g_gain, -8.0))
b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0))
g_cont = Min (8.0, Max (g_cont, -8.0))
b_cont = Min (8.0, Max (b_cont, -8.0))
r_bias = r_bias + r_cont_bias
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = g_bias + g_cont_bias
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = b_bias + b_cont_bias
b_bias = Min (512.0, Max (b_bias, -512.0))
#---------- gamma curves corrections process in accordance with gray world theory
#----------- RGB values calculation
r_gain_cont_ave = RCS_Ave_0 * r_gain + r_bias + (r_cont - 1) *(RCS_Ave_0 - 128)
g_gain_cont_ave = RCS_Ave_1 * g_gain + g_bias + (g_cont - 1) *(RCS_Ave_1 - 128)
b_gain_cont_ave = RCS_Ave_2 * b_gain + b_bias + (b_cont - 1) *(RCS_Ave_2 - 128)
#----------- RGB gamma corrections values calcul
# In gray world theory, in YUV range, we increase or decrease average value to ref = 128.0, but in RGB range
# average of channel average values is better, with average of channel average value after gain process the
# picture light is better
# In gamma process, to incresae or decrease average value, we use gamma args. To find this gamma args, we
# solve this equation ref = pow(average value/255.0,1/gamma args)
# Gamma corrections are calculated with gain output, because is more refine than calculated with gain and cont output
ref = (RCS_Ave_0 * r_gain + r_bias + RCS_Ave_1 * g_gain + g_bias + RCS_Ave_2 * b_gain + b_bias)/3.0
rpow_strength = (preset == 1) ? 0.0 : ((preset == 2) || (preset == 3) ? 1.0 : rpow_strength)
r_rpow = 1 + (log((RCS_Ave_0 * r_gain + r_bias)/255.0)/log(ref/255.0) -1) * rpow_strength
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 + (log((RCS_Ave_1* g_gain + g_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 + (log((RCS_Ave_2 * b_gain + b_bias)/255.0)/log(ref/255.0) -1) * rpow_strength
b_rpow = Min (4.0, Max (b_rpow, 0.1))
#----------- RGB correction with spow curve calcul
#------- Spow process is enable in default mode, spmid and pord args default values increase
#------- rpow process action, thus we get more color saturation but also more dark aeras.
#------- Spow for rpow is like contrast for gain. Thus i use the same factor to get automatic
#------- weigthed spow arg
auto_spow = (preset == 2) ? false : ((preset == 1)|| (preset == 3) ? true : auto_spow)
r_spow = (!auto_spow) ? 1 - (1 - 1/r_rpow) * spow_strength : \
1 - (1 - 1/r_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_0)/255.0
r_spow = Min (4.0, Max (r_spow, 0.1))
g_spow = (!auto_spow) ? 1 - (1 - 1/g_rpow) * spow_strength : \
1 - (1 - 1/g_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_1)/255.0
g_spow = Min (4.0, Max (g_spow, 0.1))
b_spow = (!auto_spow) ? 1 - (1 - 1/b_rpow) * spow_strength : \
1 - (1 - 1/b_rpow) * spow_strength * (255.0 - RCS_MinMaxDiff_2)/255.0
b_spow = Min (4.0, Max (b_spow, 0.1))
r_spmid = (r_spow == 1.0) ? 0.5 : (RCS_Ave_0 * r_gain + r_bias)/255.0
r_spmid = Min (0.99, Max (r_spmid, 0.01))
g_spmid = (g_spow == 1.0) ? 0.5 : (RCS_Ave_1* g_gain + g_bias)/255.0
g_spmid = Min (0.99, Max (g_spmid, 0.01))
b_spmid = (b_spow == 1.0) ? 0.5 : (RCS_Ave_2 * b_gain + b_bias)/255.0
b_spmid = Min (0.99, Max (b_spmid, 0.01))
#---------- bias corrections process in accordance with gray world theory
#----------- RGB bias corrections extraction and calcul
RGBAdapt( RGB_clip, \
R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
RT_RgbChanStats( LAST, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
dr = ref - RCS_Ave_0 # better result with average of average values given by gain process
dg = ref - RCS_Ave_1
db = ref - RCS_Ave_2
bias_strength = (preset == 1) || (preset == 3) ? 1.0 : ((preset == 2) ? 0.0 : bias_strength)
r_bias = (r_bias + dr * bias_strength)
r_bias = Min (512.0, Max (r_bias, -512.0))
g_bias = (g_bias + dg * bias_strength)
g_bias = Min (512.0, Max (g_bias, -512.0))
b_bias = (b_bias + db * bias_strength)
b_bias = Min (512.0, Max (b_bias, -512.0))
RGBAdapt( RGB_clip, \
R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
(blanklip == 0) ? RGB_clip : last
#----------- variables strings are tuned in global mode for data display in following ScriptClip
global r_args1 = (!show_info)? nop : RT_String(" R_bias=%7.3f : R_gain=%7.3f : R_cont =%7.3f",r_bias, r_gain, r_cont)
global r_args2 = (!show_info)? nop : RT_String(" R_rpow=%7.3f : R_spow=%7.3f : R_spmid=%7.3f",r_rpow,r_spow,r_spmid)
global g_args1 = (!show_info)? nop : RT_String(" G_bias=%7.3f : G_gain=%7.3f : G_cont =%7.3f",g_bias, g_gain, g_cont)
global g_args2 = (!show_info)? nop : RT_String(" G_rpow=%7.3f : G_spow=%7.3f : G_spmid=%7.3f",g_rpow, g_spow, g_spmid)
global b_args1 = (!show_info)? nop : RT_String(" B_bias=%7.3f : B_gain=%7.3f : B_cont =%7.3f",b_bias, b_gain, b_cont)
global b_args2 = (!show_info)? nop : RT_String(" B_rpow=%7.3f : B_spow=%7.3f : B_spmid=%7.3f",b_rpow, b_spow, b_spmid)
return last """, args = "RGB_clip, show_info, x, y, w , h, preset, gain_strength, threshold, auto_cont, cont_strength, auto_spow,"+\
"rpow_strength, spow_strength, pord, bias_strength")
Bernardd
7th November 2016, 19:24
The script end
#--------- datas display process
(!show_info) ? last :\
ScriptClip(last, """
#--------- start RGB values extraction for display
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
start_ave = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3.0
r_start1 = RT_String("Departure : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d",RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0)
g_start1 = RT_String("Departure : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d",RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1)
b_start1 = RT_String("Departure : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d",RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2)
#--------- final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
r_end1 = RT_String("Finish : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d", RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0)
g_end1 = RT_String("Finish : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d", RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1)
b_end1 = RT_String("Finish : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d", RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2)
#-------- display
CWID=65 CHIT=25 # display Width and Height in Subtitle characters
MinWid=CWID*10 MinHit=CHIT*20 # RT_Subtitle required width height in pixels (fixed font size is 10x20)
TooSmall=(Width<MinWid || Height<MinHit)
S=RT_String("\nchannels averages average : %f selected preset : %d\n" +
\ "Red values :\n" +
\ "%s\n%s\n%s\n%s\n\n" +
\ "Green values :\n" +
\ "%s\n%s\n%s\n%s\n\n" +
\ "Blue values :\n" +
\ "%s\n%s\n%s\n%s\n\n" +
\ "channels averages average : %f",
\ start_ave, preset,
\ r_start1, r_args1, r_args2, r_end1,
\ g_start1, g_args1, g_args2, g_end1,
\ b_start1, b_args1, g_args2, b_end1,
\ (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2 )/3,Esc=(TooSmall)?0:1)
(TooSmall)
\ ? Subtitle(S,Font="Courier New",lsp=0,text_color=$00FFFF00,halo_color=$00000000,size=height/float(CHIT),Font_width=width/FloaT(CWID))
\ : RT_Subtitle("%s",S)
return last """, args = "RGB_clip, x, y, w , h, threshold, preset")
#-------- display scrutinized aera
scrutinized_green = (!show_scrutinized)? nop : BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = (!show_scrutinized)? nop : Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = (!show_scrutinized)? nop : Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = (!show_scrutinized)? nop : Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = (!show_scrutinized)? nop : Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
(!show_scrutinized)? last : scrutinized
#--------- End of RGB color space process
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
}
Bernard
StainlessS
8th November 2016, 02:21
i have not kept your multi-instance capable amend
Dont know why not, you could have added an additional function to show preset windowed display, it is very handy to have GScript within your filter script.
But, your choice, may your god be with you ... Peace and love :)
EDIT: By all means have preset in the function, BUT, maybe another function for AvsPMod sliders use (Not a good idea to import that stuff into all instances of your plug, keep separate [also avoid having to edit the AvsPmod stuff Out/In, I'm assuming that AvsPmod
stuff does not have to be at main level]).
Bernardd
8th November 2016, 13:35
I have added an additional function to show preset windowed display, because all other args are not tunable when preset is not 0. It is a mark to explain why adjust one args can be uneffective.
Now i search the better use for the script. Thus when i have to do some correction, i prefer use a script method that i know a little. It is more easy for me.
I know, write with Gscript is not difficult, but it is new for me and now i am not ready. I search to solve one problem after the other.
With you, i am learning. Thanks :)
Bernard
StainlessS
8th November 2016, 15:51
Come on Bernardd, you dont have to be any kind of scripting wizard to use eg
if(something) {
Do_Something()
} else if(something_else) {
Do_Something_else()
} else {
Do_Otherwise()
}
a lot more convenient than lots of ternary conditions, you can include/exclude loads of lines all at once.
Bernardd
9th November 2016, 02:06
Hi StainlessS
You have right
I have saw the benefit of GScript, but now my problem is :
exists a new condition to get a more automatic process, and on which frame datas ?
Thus optimise the script is now a second priority for me.
If i find or if i do not find nothing, i shall come back with script with Gscript use.
Bernard
Bernardd
20th December 2016, 10:54
Hello StainlessS,
In following post is new version of my script.
Now with script, the user have three choices :
- output with gain, rpow and bias process (preset 1)
- output with gain, cont, rpow, spow and bias process (preset 2)
- output with automatic choice (preset 0)
The user must tune threshold arg of RgbChanStats for RGB min, max, and minmax diff values. It is very useful for
define gain effect power. But it is also necassary in automatic choice mode, because auto choice is based on minmax values.
These threshold is also important, because a frame with a big minmaxdiff value variation from next and previous frame will be
more light or more dark, we can observe this with a source like the frame 2111 of John Meyer's script demo sample
(http://forum.doom9.org/showthread.php?p=1780794#post1780794 )
To choice help, call script have a comparison mode to display original, basic coloryuv autowhite process, preset 1, preset 2
and selected preset clip versions.
The script uses now Gscript plugin, conditional line write are now more easy, but quote use is not so evident.
I have not follow the whole of your Gscript sample on my old script version. Thus i call Gscript fonction twice.
One to include Gscript in GScripClip and second to include GScriptClip in Gscript. With this way, i think it
is not optimised, but i understand that i do. If you can give me some explanations, i should be satisfied.
Thanks.
Bernard
Bernardd
20th December 2016, 10:59
Call script
AVISource("C:\.............\your video.avi")
LoadPlugin("C:\............\GRunT.dll")
LoadPlugin("C:\............\GScript.dll")
LoadPlugin("C:\............\RGBAdapt.dll")
LoadPlugin("C:\............\RT_Stats26.dll")
# display tunings
comparison = true
show_scrutinized = true
show_info = false
# color space matrix tuning and specify the source rectangle under scrutiny
matrix = "Rec601"
x = 0.10
Y= 0.10
w = 0.10
h = 0.10
#extreme pixels percentage to be ignored when datas extraction
threshold = 0.10
# automatic white balance preset tunings
preset = 0
# gamma process tuning
pord = false #pord args changes give similar results
# If you use AvsPmod user sliders you can delete comment for follow lines
#~ [<separator="display tunings">]
#~ comparison = Select([<"show different settings - (false ou true) default = false = 0", 0, 1, 1>], false , true)
#~ show_scrutinized = Select([<"show scrutinized aera - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_info = Select([<"show datas - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="color space matrix tuning">]
#~ matrix = Select([<"color matrix - (Rec 601= 0 ou Rec 709 =1) = default = 0", 0, 1, 0>], "Rec601" , "Rec709")
#~ [<separator=""specify the source rectangle under scrutiny and percentage extreme pixels to ignore">]
#~ x = [<"ignore pixels on left - width percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ Y= [<"ignore pixels on top - heigth percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ w = [<"ignore pixels on right - width percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ h = [<"ignore pixels on bottom - heigth percentage - default : 0.00", 0.00, 0.99, 0.07>]
#~ [<separator=""specify the extreme pixels percentage to be ignored when datas extraction">]
#~ threshold = [<"percentage for extreme pixels to be ignored - default : 0.10", 0.00, 1.00, 0.05>]
#~ [<separator="automatic white balance preset tunings">]
#~ preset = Select([<"preset default = 0", 0, 2, 0>], 0 , 1, 2)
#~ pord = false # pord = Select([<"pord - (false = rpow before spow ) default = false = 0", 0, 1, 0>], false , true) # pord args changes give similar results
Gscript("""
output = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold = threshold, pord = pord, preset = preset)
if (!comparison) {output}
else {
if (!isRGB) {ColorYUV_AWB = ColorYUV(autowhite = true)}
else { colorYUV_AWB = ConvertToYV12(matrix=matrix).ColorYUV(autowhite = true).ConvertToRGB24(matrix=matrix)}
preset_1 = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = false, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold = 0.1, pord = pord, preset = 1)
preset_2 = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold = 0.1, pord = pord, preset = 2)
StackVertical(\
StackHorizontal(blankclip(last).AddBorders(0, 50, 0, 0, color=$000000),\
preset_1.AddBorders(0, 50, 0, 0, color=$000000). Subtitle ("gain rpow and bias process but no cont and no spow process"+ \
"\n threshold : 0.1 preset 1" , lsp = 20),\
preset_2.AddBorders(0, 50, 0, 0, color=$000000). Subtitle ("gain cont rpow spow and bias process"+ \
"\n threshold : 0.1 preset 2" , lsp = 20)),\
StackHorizontal(last.AddBorders(0, 0, 0, 50, color=$000000).Subtitle("original", y = height(last)),\
colorYUV_AWB.AddBorders(0, 0, 0, 50, color=$000000).Subtitle ("As a reminder, classical ColorYUV awb", y = height(last)),\
output.AddBorders(0, 0, 0, 50, color=$000000).Subtitle ("Selected output"+ "\n threshold : " + LeftStr(string(threshold),4) + \
" preset = " +string(preset), lsp = 20, y = height(last))))}
""")
Bernardd
20th December 2016, 11:05
Script function part 1
/*
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=170642 #
#------------------------------------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need RT_Stats plugin -------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=165479 #
#------------------------------------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=139337 #
#-----------------------------------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need GScript plugin ----------------------------------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=147846 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
*/
# ---------------------------- function script -------------------------------------
function RGBAdapt_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
float "threshold", int "preset", bool "pord")
{
myName="RGBAdapt_awb_process: "
Assert(RT_FunctionExist("RGBAdapt"),myName+"RGBAdapt plugin must be loaded, http://forum.doom9.org/showthread.php?t=170642")
Assert(RT_FunctionExist("GScriptClip"),myName+"GRunT plugin must be loaded, http://forum.doom9.org/showthread.php?t=139337")
Assert(RT_FunctionExist("GScript"),myName+"GScript plugin must be loaded, http://forum.doom9.org/showthread.php?t=147846")
Assert(IsYV12(clip) || IsRGB(clip),RT_String("%sInput video colorspace must be YV12 or RGB, not YUV",myName))
matrix = Default(matrix, "Rec601") # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709",RT_String("%smatrix 'Rec601' or 'Rec709'('%s')",myName,matrix))
show_scrutinized = Default(show_scrutinized, false) # show scrutinized area or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.0)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= x <= 0.99,RT_String("%s0.0 <= x <= 0.99(%f)",myName,x))
y = float(Default(y,0.0)) #height percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= y <= 0.99,RT_String("%s0.0 <= y <= 0.99(%f)",myName,y))
w = float(Default(w,0.0)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= w <= 0.99,RT_String("%s0.0 <= w <= 0.99(%f)",myName,w))
Assert(0.0 <= (x+w) <= 0.99 ,RT_String("%s0.0 <= (x+w) <= 0.99(%f)",myName,x+w))
h = float(Default(h,0.0)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= h <= 0.99,RT_String("%s0.0 <= h <= 0.99(%f)",myName,h))
Assert(0.0 <= (y+h) <= 0.99 ,RT_String("%s0.0 <= (y+h) <= 0.99(%f)",myName,y+h))
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(0.0 <= threshold <= 1.0,RT_String("%s0.0 <= threshold <= 1.0(%f)",myName,threshold))
pord = Default(pord, false) # RGBAdapt pord arg, his changes give similar results
preset= Int(Default(preset, 0))
Assert(0 <= preset <= 2,RT_String("%s preset = 0,1 or 2 ( no %d)",myName,preset))
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#--------- RGB color space process
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#----------------- technical string definition to avoid quote use errors with ScriptClip and Gscript mix
r_args1_string = " R_bias=%7.3f : R_gain=%7.3f : R_cont =%7.3f"
r_args2_string = " R_rpow=%7.3f : R_spow=%7.3f : R_spmid=%7.3f"
g_args1_string = " G_bias=%7.3f : G_gain=%7.3f : G_cont =%7.3f"
g_args2_string = " G_rpow=%7.3f : G_spow=%7.3f : G_spmid=%7.3f"
b_args1_string = " B_bias=%7.3f : B_gain=%7.3f : B_cont =%7.3f"
b_args2_string = " B_rpow=%7.3f : B_spow=%7.3f : B_spmid=%7.3f"
start_string = "Departure : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d"
end_string = "Finish : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d"
display_string = "\nchannels averages average : %f used preset : %-d\n" +
\ "Red values :\n"+
\ "%s\n%s\n%s\n%s\n\n"+
\ "Green values :\n"+
\ "%s\n%s\n%s\n%s\n\n"+
\ "Blue values :\n"+
\ "%s\n%s\n%s\n%s\n\n"+
\ "channels averages average : %f"
rt_string_format_string = "%s"
police_string = "Courier New"
#--------- AWB process
ScriptClip( RGB_clip,"""
Gscript("
#---------- First pass : gain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
# ------ detection BlankClip and condition to avoid division by 0
blankclip = RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01) RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
#------ preset automatic selection
ave_ave = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3.0
min_minmaxdiff = Min(RCS_MinMaxDiff_0, RCS_MinMaxDiff_1, RCS_MinMaxDiff_2)
if (preset == 0) {if (min_minmaxdiff < ave_ave) {preset = 2} else {preset = 1}}
#---- gain args calculation
r_gain = 255.0/RCS_MinMaxDiff_0 g_gain = 255.0/RCS_MinMaxDiff_1 b_gain = 255.0/RCS_MinMaxDiff_2
r_gain_bias = - RCS_Min_0 * r_gain g_gain_bias = - RCS_Min_1 * g_gain b_gain_bias = - RCS_Min_2 * b_gain
#---- cont args calculation
# Cont is dangerous, because it can overshoot light and dark, but it is necessary to help to find good correction for very big
# color cast. Thus it is desable for preset 1. It is enable for preset 2 with a automatic weighted autocont strength
# based on my tests results. I observe that picture do'nt need contraste is picture, which have a large histogram, which have
# min value near 0 et max value near 255, which have bigger min max diff value.
if (preset == 2) {r_cont = 1 + (r_gain - 1) * (255.0 - RCS_MinMaxDiff_0)/255.0
r_cont_max = RCS_Max_0 * r_gain + r_gain_bias + (r_cont - 1) *(RCS_Max_0 - 128)
r_cont_bias = (255 - r_cont_max) * (255.0 - RCS_MinMaxDiff_0)/255.0
g_cont = 1 + (g_gain - 1) * (255.0 - RCS_MinMaxDiff_1)/255.0
g_cont_max = RCS_Max_1 * g_gain + g_gain_bias + (g_cont - 1) *(RCS_Max_1 - 128)
g_cont_bias = (255 - g_cont_max) * (255.0 - RCS_MinMaxDiff_1)/255.0
b_cont =1 + (b_gain - 1) * (255.0 - RCS_MinMaxDiff_2)/255.0
b_cont_max = RCS_Max_2 * b_gain + b_gain_bias + (b_cont - 1) *(RCS_Max_2 - 128)
b_cont_bias = (255 - b_cont_max) * (255.0 - RCS_MinMaxDiff_2)/255.0 }
else { r_cont = 1.0 g_cont = 1.0 b_cont = 1.0
r_cont_bias = 0.0 g_cont_bias = 0.0 b_cont_bias = 0.0}
r_bias = r_gain_bias + r_cont_bias g_bias = g_gain_bias + g_cont_bias b_bias = b_gain_bias + b_cont_bias
#----gamma args calculation in accordance with gray world theory
# In gray world theory, in YUV range, we increase or decrease average value to ref = 128.0, but in RGB range
# ref = average of channel average values is better.
# With preset 2, average of channel average value after gain process without cont process give a better picture light.
# In gamma process, to incresae or decrease average value, we use gamma args. To find this gamma args, we
# solve this equation ref = pow(average value/255.0,1/gamma args)
ref = (RCS_Ave_0 * r_gain + r_gain_bias + RCS_Ave_1 * g_gain + g_gain_bias + RCS_Ave_2 * b_gain + b_gain_bias)/3.0
r_rpow = 1 + (log((RCS_Ave_0 * r_gain + r_gain_bias)/255.0)/log(ref/255.0) - 1)
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 + (log((RCS_Ave_1 * g_gain + g_gain_bias)/255.0)/log(ref/255.0) - 1)
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 + (log((RCS_Ave_2 * b_gain + b_gain_bias)/255.0)/log(ref/255.0) - 1)
b_rpow = Min (4.0, Max (b_rpow, 0.1))
# spow, spmid calculation, pord is operator choice
#------- Spow, spmid and pord args computed values increase rpow process action,
#------- thus we get more color saturation but also more dark aeras.
#------- Spow for rpow is like contrast for gain. Thus in preset 2, i do'nt use spow,
#------- an with preset 3, i use a factor to get automatic weigthed spow arg
if (preset == 2) { Ave_max = Max(RCS_Ave_0 * r_gain + r_gain_bias , \
Max(RCS_Ave_1 * g_gain + g_gain_bias, RCS_Ave_2 * b_gain + b_gain_bias))
r_spow = 1 + (1/r_rpow - 1) * (Ave_max - RCS_Ave_0 * r_gain - r_gain_bias)/Ave_max
g_spow = 1 + (1/g_rpow - 1) * (Ave_max - RCS_Ave_1 * g_gain - g_gain_bias)/Ave_max
b_spow = 1 + (1/b_rpow - 1) * (Ave_max - RCS_Ave_2 * b_gain - b_gain_bias)/Ave_max
r_spmid = (RCS_Ave_0 * r_gain + r_gain_bias)/255.0
g_spmid = (RCS_Ave_1* g_gain + g_gain_bias)/255.0
b_spmid = (RCS_Ave_2 * b_gain + b_gain_bias)/255.0 }
else { r_spow = 1.0 g_spow = 1.0 b_spow = 1.0
r_spmid = 0.5 g_spmid = 0.5 b_spmid = 0.5}
#--------- bias gain cont spow and spmid in RGBadapt args range
r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))
r_gain = Min (8.0, Max (r_gain, -8.0)) g_gain = Min (8.0, Max (g_gain, -8.0)) b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0)) g_cont = Min (8.0, Max (g_cont, -8.0)) b_cont = Min (8.0, Max (b_cont, -8.0))
r_spow = Min (4.0, Max (r_spow, 0.1)) g_spow = Min (4.0, Max (g_spow, 0.1)) b_spow = Min (4.0, Max (b_spow, 0.1))
r_spmid = Min (0.99, Max (r_spmid, 0.01)) g_spmid = Min (0.99, Max (g_spmid, 0.01)) b_spmid = Min (0.99, Max (b_spmid, 0.01))
#---------- bias corrections in accordance with gray world theory
#----------- bias corrections extraction and calcul
RGBAdapt( RGB_clip, \
R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
# Ref for bias corrections is calculated with gain output, because is more light than calculated with gain cont and gamma output
dr = ref - RCS_Ave_0 dg = ref - RCS_Ave_1 db = ref - RCS_Ave_2
r_bias = (r_gain_bias + r_cont_bias + dr) g_bias = (g_gain_bias + g_cont_bias + dg) b_bias = (b_gain_bias + b_cont_bias + db)
r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))
#------------ AWB output with gain cont rpow spow and bias process in accordance with preset
RGBAdapt( RGB_clip, \
R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow, R_spow = r_spow, R_SPMid = r_spmid, R_Pord = pord,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow, G_spow = g_spow, G_SPMid = g_spmid, G_Pord = pord,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow, B_spow = b_spow, B_SPMid = b_spmid, B_Pord = pord)
(blankclip == 0) ? RGB_clip : last
#----------- variables strings are tuned in global mode for data display in following ScriptClip
if (show_info) { global preset = preset
global r_args1 = RT_String(r_args1_string,r_bias, r_gain, r_cont)
global r_args2 = RT_String(r_args2_string,r_rpow,r_spow,r_spmid)
global g_args1 = RT_String(g_args1_string,g_bias, g_gain, g_cont)
global g_args2 = RT_String(g_args2_string,g_rpow, g_spow, g_spmid)
global b_args1 = RT_String(b_args1_string,b_bias, b_gain, b_cont)
global b_args2 = RT_String(b_args2_string,b_rpow, b_spow, b_spmid) }
return last ")""", args = " RGB_clip, show_info, x, y, w , h, preset, threshold, pord,"+\
"r_args1_string, r_args2_string, g_args1_string, g_args2_string, b_args1_string, b_args2_string")
#--------- datas display process
Gscript(""" if (show_info) { ScriptClip(last,"
#--------- start RGB values extraction for display
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
start_ave = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3.0
r_start1 = RT_String(start_string,RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0)
g_start1 = RT_String(start_string,RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1)
b_start1 = RT_String(start_string,RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2)
#--------- final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
r_end1 = RT_String(end_string, RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0)
g_end1 = RT_String(end_string, RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1)
b_end1 = RT_String(end_string, RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2)
#-------- display
CWID=65 CHIT=25 # display Width and Height in Subtitle characters
MinWid=CWID*10 MinHit=CHIT*20 # RT_Subtitle required width height in pixels (fixed font size is 10x20)
TooSmall=(Width<MinWid || Height<MinHit)
S=RT_String(display_string,
\ start_ave, preset,
\ r_start1, r_args1, r_args2, r_end1,
\ g_start1, g_args1, g_args2, g_end1,
\ b_start1, b_args1, b_args2, b_end1,
\ (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2 )/3, Esc=(TooSmall)?0:1)
(TooSmall)
\ ? Subtitle(S,Font=police_string,lsp=0,text_color=$00FFFF00,halo_color=$00000000,size=height/float(CHIT),Font_width=width/FloaT(CWID))
\ : RT_Subtitle(rt_string_format_string,S)
return last ", args = "RGB_clip, x, y, w , h, threshold,start_string, end_string, display_string, rt_string_format_string, police_string") }
else { return last }
Bernardd
20th December 2016, 11:06
Script function part 2
#-------- display scrutinized aera
if (show_scrutinized) {
scrutinized_green = BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
return scrutinized } """)
#--------- End of RGB color space process
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
}
Bernardd
7th January 2017, 22:24
Happy new year for all
Below the last version of my script.
In this version i have deleted spow process, because after many tests, her efficiency was not proved.
The script have always technical args to display comparison, scrutinized area and computed datas. It have always the args to define scrutinized area
and threshold of RgbChanStats for RGB min, max, and minmax diff values. Default value can be enough, but it must be increase if you get a unhomogenous
process for several following frames.
Now the script computes one automatic white balance with gain, rpow and final bias process. For big color cast the script use also contrast process.
In automatic mode, the contrast use is enable if difference between max average channel value and min average channel value is bigger than threshold
(in color cast, one channel average value is often bigger thant the the two others). Automatic contrast use is only for big color cast, thus default threshold is 128.
Threshold_auto arg is used to define the contrast automatic toggle. When it is equal to 0, contrast is always enable, when it is equal to 255 contrast is always disable,
between 0 and 255, contrast is enabled if min max average valus diff is bigger than it.
I think that you can get a better automatic white balance with this combination, than with ColorYUV (autowhite = true). But perhaps you can found gain too strong.
The script have thus a gain strength arg to decrease and even to disable the gain. It have also a rpow strength arg and a bias strength arg to decrease and even to
disable these process.
In default mode, the script use combination of gain rpow and bias, but with these three last args you can make three other combination, gain only, gain and rpow,
gain and bias. To help to make a choice, on comparison display below the green line these three combinations are displayed.
The script have always a call part and a function part. These parts are in following posts.
Bernard
Bernardd
7th January 2017, 22:25
Call lines with AvsPMod usersliders opportunity, il you want.
AVISource("C:\.............\your video.avi")
LoadPlugin("C:\............\GRunT.dll")
LoadPlugin("C:\............\GScript.dll")
LoadPlugin("C:\............\RGBAdapt.dll")
LoadPlugin("C:\............\RT_Stats26.dll")
# display tunings
comparison = true
show_scrutinized = true
show_info = false
# color space matrix tuning and specify the source rectangle under scrutiny
matrix = "Rec601"
x = 0.10
Y= 0.10
w = 0.10
h = 0.10
#extreme pixels percentage to be ignored when datas extraction
threshold = 0.10
# automatic white balance preset tunings
threshold_auto = 128
gain_strength = 1.0
rpow_strength = 1.0
bias_strength = 1.0
# If you use AvsPmod user sliders you can delete comment for following lines
#~ [<separator="display tunings">]
#~ comparison = Select([<"show different settings - (false ou true) default = false = 0", 0, 1, 1>], false , true)
#~ show_scrutinized = Select([<"show scrutinized aera - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_info = Select([<"show datas - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="color space matrix tuning">]
#~ matrix = Select([<"color matrix - (Rec 601= 0 ou Rec 709 =1) = default = 0", 0, 1, 0>], "Rec601" , "Rec709")
#~ [<separator=""specify the source rectangle under scrutiny and percentage extreme pixels to ignore">]
#~ x = [<"ignore pixels on left - width percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ Y= [<"ignore pixels on top - heigth percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ w = [<"ignore pixels on right - width percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ h = [<"ignore pixels on bottom - heigth percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ [<separator=""specify the extreme pixels percentage to be ignored when datas extraction">]
#~ threshold = [<"percentage for extreme pixels to be ignored - default : 0.10", 0.00, 1.00, 0.1>]
#~ [<separator="automatic white balance tunings">]
#~ threshold_auto = [<"threshold for enable cont process - default : 128", 0, 255, 128>]
#~ gain_strength = [<"gain strength - default : 1.0", 0.0, 1.0, 1.0>]
#~ rpow_strength = [<"rpow strength - default : 1.0", 0.0, 1.0, 1.0>]
#~ bias_strength = [<"final bias strength - default : 1.0", 0.0, 1.0, 1.0>]
Gscript("""
output = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, threshold = threshold, \
gain_strength = gain_strength, rpow_strength = rpow_strength, bias_strength = bias_strength,threshold_auto = threshold_auto)
if (!comparison) {output}
else {
if (!isRGB) {ColorYUV_AWB = ColorYUV(autowhite = true)}
else { colorYUV_AWB = ConvertToYV12(matrix=matrix).ColorYUV(autowhite = true).ConvertToRGB24(matrix=matrix)}
without_contrast = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold_auto = 255)
with_contrast = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold_auto = 0)
gain_rpow = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold_auto = threshold_auto, bias_strength = 0.0)
gain_bias = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold_auto = threshold_auto, rpow_strength = 0.0)
only_gain = RGBAdapt_awb_process(matrix = matrix, show_scrutinized = show_scrutinized, show_info = show_info, x = x, y = y, w = w, h = h, \
threshold = 0.1, threshold_auto = threshold_auto, rpow_strength = 0.0, bias_strength = 0.0)
if (threshold_auto == 255) {contrast_label = "without contrast"} else {if (threshold_auto == 0) \
{contrast_label = "with contrast"} else {contrast_label = "contrast in accordance with threshold"}}
StackVertical(\
StackHorizontal(blankclip(last).AddBorders(0, 20, 0, 0, color=$000000),\
without_contrast.AddBorders(0, 20, 0, 0, color=$000000). Subtitle ("gain rpow and bias process without contrast"),\
with_contrast.AddBorders(0, 20, 0, 0, color=$000000). Subtitle ("gain rpow and bias process with contrast")),\
StackHorizontal(last.AddBorders(0, 0, 0, 20, color=$000000).Subtitle("original", y = height(last)),\
colorYUV_AWB.AddBorders(0, 0, 0, 20, color=$000000).Subtitle ("As a reminder, classical ColorYUV awb", y = height(last)),\
output.AddBorders(0, 0, 0, 20, color=$000000).Subtitle ("Selected output"+ " " +string(contrast_label), y = height(last))),\
StackHorizontal(only_gain.AddBorders(0, 0, 0, 20, color=$000000). Subtitle ("only gain "+ " " +string(contrast_label), y = height(last)),\
gain_bias.AddBorders(0, 0, 0, 20, color=$000000). Subtitle ("only gain and bias"+ " " +string(contrast_label), y = height(last)),\
gain_rpow.AddBorders(0, 0, 0, 20, color=$000000). Subtitle ("only gain and rpow"+ " " +string(contrast_label), y = height(last)))\
.Letterbox(20, 0, x1=0, x2=0, color=$00FF00).Subtitle( "Perhaps other good combinations ?",align = 8))}
""")
Bernardd
7th January 2017, 22:26
End - Function lines
/*
#----------------------------------------------based on RGBADapt plugin ---------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=170642 #
#------------------------------------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need RT_Stats plugin -------------------------------------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=165479 #
#------------------------------------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need GRunT plugin ----------------------------------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=139337 #
#-----------------------------------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need GScript plugin ----------------------------------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=147846 #
#----------------------------------------------------------------------------------------------------------------------------------------------- #
*/
# ---------------------------- function script -------------------------------------
function RGBAdapt_awb_process(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h", \
float "threshold", int "threshold_auto", float "gain_strength", float "rpow_strength", float "bias_strength")
{
myName="RGBAdapt_awb_process: "
Assert(RT_FunctionExist("RGBAdapt"),myName+"RGBAdapt plugin must be loaded, http://forum.doom9.org/showthread.php?t=170642")
Assert(RT_FunctionExist("GScriptClip"),myName+"GRunT plugin must be loaded, http://forum.doom9.org/showthread.php?t=139337")
Assert(RT_FunctionExist("GScript"),myName+"GScript plugin must be loaded, http://forum.doom9.org/showthread.php?t=147846")
Assert(IsYV12(clip) || IsRGB(clip),RT_String("%sInput video colorspace must be YV12 or RGB, not YUV",myName))
matrix = Default(matrix, "Rec601") # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709",RT_String("%smatrix 'Rec601' or 'Rec709'('%s')",myName,matrix))
show_scrutinized = Default(show_scrutinized, false) # show scrutinized area or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.0)) #width percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= x <= 0.99,RT_String("%s0.0 <= x <= 0.99(%f)",myName,x))
y = float(Default(y,0.0)) #height percentage to specify the coords source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= y <= 0.99,RT_String("%s0.0 <= y <= 0.99(%f)",myName,y))
w = float(Default(w,0.0)) #coords specify the source rectangle under scrutiny, the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= w <= 0.99,RT_String("%s0.0 <= w <= 0.99(%f)",myName,w))
Assert(0.0 <= (x+w) <= 0.99 ,RT_String("%s0.0 <= (x+w) <= 0.99(%f)",myName,x+w))
h = float(Default(h,0.0)) #coords specify the source rectangle under scrutiny , the default : x = y = h = w = 0.00 is full frame
Assert(0.0 <= h <= 0.99,RT_String("%s0.0 <= h <= 0.99(%f)",myName,h))
Assert(0.0 <= (y+h) <= 0.99 ,RT_String("%s0.0 <= (y+h) <= 0.99(%f)",myName,y+h))
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(0.0 <= threshold <= 1.0,RT_String("%s0.0 <= threshold <= 1.0(%f)",myName,threshold))
threshold_auto = Int(Default(threshold_auto, 128)) # threshold for enable cont process
Assert(0 <= threshold_auto <= 255,RT_String("%s0 <= threshold_auto <= 255(%d)",myName,threshold_auto))
gain_strength = Float(Default(gain_strength, 1.0)) # gain strength
Assert(0.0 <= gain_strength <= 1.0,RT_String("%s0.0 <= gain_strength <= 1.0(%f)",myName,gain_strength))
rpow_strength = Float(Default(rpow_strength, 1.0)) #rpow strength
Assert(0.0 <= rpow_strength <= 1.0,RT_String("%s0.0 <= rpow_strength <= 1.0(%f)",myName,rpow_strength))
bias_strength = Float(Default(bias_strength, 1.0)) #bias strength
Assert(0.0 <= bias_strength <= 1.0,RT_String("%s0.0 <= bias_strength <= 1.0(%f)",myName,bias_strength))
#---------- Specify the source rectangle under scrutiny
x = int(Width(clip) * x)
y = int(Height(clip) * y)
w = int(-Width(clip) * w)
h = int(-Height(clip) * h)
#--------- RGB color space process
RGB_clip = (!isRGB(clip)) ? ConvertToRGB24(clip, matrix=matrix) : clip
#----------------- technical string definition to avoid quote use errors with ScriptClip and Gscript mix
r_args1_string = " R_bias =%7.3f : R_gain =%7.3f : R_cont =%7.3f"
r_args2_string = " R_rpow =%7.3f"
g_args1_string = " G_bias=%7.3f : G_gain=%7.3f : G_cont =%7.3f"
g_args2_string = " G_rpow=%7.3f"
b_args1_string = " B_bias=%7.3f : B_gain=%7.3f : B_cont =%7.3f"
b_args2_string = " B_rpow=%7.3f"
start_string = "Departure : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d"
end_string = "Finish : Average=%-7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d"
display_string = "\nchannels averages average : %f \nmin max average diff : %f contrast : %s\n\n" +
\ "Red values :\n" +
\ "%s\n%s\n%s\n%s\n\n" +
\ "Green values :\n" +
\ "%s\n%s\n%s\n%s\n\n" +
\ "Blue values :\n" +
\ "%s\n%s\n%s\n%s\n\n" +
\ "channels averages average : %f"
rt_string_format_string = "%s"
police_string = "Courier New"
#--------- AWB process
ScriptClip( RGB_clip,"""
Gscript("
#---------- First pass : gain process for each channel
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
# ------ detection BlankClip and condition to avoid division by 0
blankclip = RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2
RCS_MinMaxDiff_0 = Max (RCS_MinMaxDiff_0, 0.01) RCS_MinMaxDiff_1 = Max (RCS_MinMaxDiff_1, 0.01) RCS_MinMaxDiff_2 = Max (RCS_MinMaxDiff_2, 0.01)
#------ contrast automatic enable
if (Max(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2)- Min(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2) > threshold_auto) {contrast = true} else {contrast = false}
#---- gain args calculation
r_gain = 1 + (255.0/RCS_MinMaxDiff_0 - 1) * gain_strength g_gain = 1 + (255.0/RCS_MinMaxDiff_1 - 1) * gain_strength b_gain = 1 + (255.0/RCS_MinMaxDiff_2 - 1) * gain_strength
r_gain_bias = - RCS_Min_0 * r_gain * gain_strength g_gain_bias = - RCS_Min_1 * g_gain * gain_strength b_gain_bias = - RCS_Min_2 * b_gain * gain_strength
#---- cont args calculation
# Cont is dangerous, because it can overshoot light and dark, but it is necessary to help to find good correction for very big
# color cast. Thus it is enable only for big color cast with a automatic weighted autocont strength based on my tests results.
# I observe that picture do'nt need contraste is picture, which have a large histogram, which have min value near 0 and
# max value near 255, which have bigger min max diff value.
if (contrast == true){r_cont = 1 + (r_gain - 1) * (255.0 - RCS_MinMaxDiff_0)/255.0
r_cont_max = RCS_Max_0 * r_gain + r_gain_bias + (r_cont - 1) *(RCS_Max_0 - 128)
r_cont_bias = (255 - r_cont_max) * gain_strength
g_cont = 1 + (g_gain - 1) * (255.0 - RCS_MinMaxDiff_1)/255.0
g_cont_max = RCS_Max_1 * g_gain + g_gain_bias + (g_cont - 1) *(RCS_Max_1 - 128)
g_cont_bias = (255 - g_cont_max) * gain_strength
b_cont =1 + (b_gain - 1) * (255.0 - RCS_MinMaxDiff_2)/255.0
b_cont_max = RCS_Max_2 * b_gain + b_gain_bias + (b_cont - 1) *(RCS_Max_2 - 128)
b_cont_bias = (255 - b_cont_max) * gain_strength }
else { r_cont = 1.0 g_cont = 1.0 b_cont = 1.0
r_cont_bias = 0.0 g_cont_bias = 0.0 b_cont_bias = 0.0}
r_bias = r_gain_bias + r_cont_bias g_bias = g_gain_bias + g_cont_bias b_bias = b_gain_bias + b_cont_bias
#----gamma args calculation in accordance with gray world theory
# In gray world theory, in YUV range, we increase or decrease average value to ref = 128.0, but in RGB range
# ref = average of channel average values is better.
# With contrast use, average of channel average value after gain process without cont process give a better picture light.
# In gamma process, to incresae or decrease average value, we use gamma args. To find this gamma args, we
# solve this equation ref = pow(average value/255.0,1/gamma args)
ref = (RCS_Ave_0 * r_gain + r_gain_bias + RCS_Ave_1 * g_gain + g_gain_bias + RCS_Ave_2 * b_gain + b_gain_bias)/3.0
r_rpow = 1 + (log((RCS_Ave_0 * r_gain + r_gain_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 + (log((RCS_Ave_1 * g_gain + g_gain_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 + (log((RCS_Ave_2 * b_gain + b_gain_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
b_rpow = Min (4.0, Max (b_rpow, 0.1))
#--------- bias gain cont spow and spmid in RGBadapt args range
r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))
r_gain = Min (8.0, Max (r_gain, -8.0)) g_gain = Min (8.0, Max (g_gain, -8.0)) b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0)) g_cont = Min (8.0, Max (g_cont, -8.0)) b_cont = Min (8.0, Max (b_cont, -8.0))
#---------- bias corrections in accordance with gray world theory
#----------- bias corrections extraction and calcul
RGBAdapt( RGB_clip, R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow)
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 16)
# Ref for bias corrections is always calculated with gain output, because is more light than calculated with gain cont and gamma output
dr = (ref - RCS_Ave_0)* bias_strength dg = (ref - RCS_Ave_1)* bias_strength db = (ref - RCS_Ave_2)* bias_strength
r_bias = (r_gain_bias + r_cont_bias + dr) g_bias = (g_gain_bias + g_cont_bias + dg) b_bias = (b_gain_bias + b_cont_bias + db)
r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))
#------------ AWB output with gain cont rpow and bias process
RGBAdapt( RGB_clip, R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow,\
G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow,\
B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow)
(blankclip == 0) ? RGB_clip : last
#----------- variables strings are tuned in global mode for data display in following ScriptClip
if (show_info) { global contrast = contrast
global r_args1 = RT_String(r_args1_string,r_bias, r_gain, r_cont)
global r_args2 = RT_String(r_args2_string,r_rpow)
global g_args1 = RT_String(g_args1_string,g_bias, g_gain, g_cont)
global g_args2 = RT_String(g_args2_string,g_rpow)
global b_args1 = RT_String(b_args1_string,b_bias, b_gain, b_cont)
global b_args2 = RT_String(b_args2_string,b_rpow) }
return last ")""", args = " RGB_clip, show_info, x, y, w , h, threshold,threshold_auto, gain_strength, rpow_strength, bias_strength,"+\
"r_args1_string, r_args2_string, g_args1_string, g_args2_string, b_args1_string, b_args2_string")
#--------- datas display process
Gscript(""" if (show_info) { ScriptClip(last,"
#--------- start RGB values extraction for display
RT_RgbChanStats( RGB_clip, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+16)
start_ave = (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2)/3.0 start_minmax = Max(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2)- Min(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2)
r_start1 = RT_String(start_string,RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0)
g_start1 = RT_String(start_string,RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1)
b_start1 = RT_String(start_string,RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2)
#--------- final RGB values extraction for display
RT_RgbChanStats( last, x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16)
r_end1 = RT_String(end_string, RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0)
g_end1 = RT_String(end_string, RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1)
b_end1 = RT_String(end_string, RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2)
#-------- display
CWID=65 CHIT=25 # display Width and Height in Subtitle characters
MinWid=CWID*10 MinHit=CHIT*20 # RT_Subtitle required width height in pixels (fixed font size is 10x20)
TooSmall=(Width<MinWid || Height<MinHit)
S=RT_String(display_string,
\ start_ave, start_minmax, contrast,
\ r_start1, r_args1, r_args2, r_end1,
\ g_start1, g_args1, g_args2, g_end1,
\ b_start1, b_args1, b_args2, b_end1,
\ (RCS_Ave_0 + RCS_Ave_1 + RCS_Ave_2 )/3, Esc=(TooSmall)?0:1)
(TooSmall)
\ ? Subtitle(S,Font=police_string,lsp=0,text_color=$00FFFF00,halo_color=$00000000,size=height/float(CHIT),Font_width=width/FloaT(CWID))
\ : RT_Subtitle(rt_string_format_string,S)
return last ", args = "RGB_clip, x, y, w , h, threshold,start_string, end_string, display_string, rt_string_format_string, police_string") }
else { return last }
#-------- display scrutinized aera
if (show_scrutinized) {
scrutinized_green = BlankClip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$00FF00)
scrutinized_white = Blankclip(RGB_clip, width = (Width(last)-x+w), height = (Height(last)-y+h), color=$FFFFFF)
scrutinized_int = Blankclip(RGB_clip, width = (Width(scrutinized_white)-4), height = (Height(scrutinized_white)-4),\
color=000000)
scrutinized_mask = Overlay(scrutinized_white, scrutinized_int, x=2, y=2, opacity=1.0, mode="multiply", greymask=true,\
ignore_conditional=false, pc_range=false)
scrutinized = Overlay(last, scrutinized_green, mask = scrutinized_mask, x=x, y=y, opacity=1.0, mode="blend", greymask=true,\
ignore_conditional=false, pc_range=false)
return scrutinized } """)
#--------- End of RGB color space process
!isRGB(clip) ? ConvertToYV12(last, matrix=matrix) : last
}
Mounir
8th January 2017, 02:54
Can you upload the .avs directly , thank you
StainlessS
8th January 2017, 03:19
Copy and paste aint that difficult, but here you go:- http://www.mediafire.com/file/93pv92jq5jy9fff/RGBAdapt_awb_process.zip
Mounir
8th January 2017, 12:17
Invalid arguments for RGBAdapt_awb_process()
Error on line 82 also (in the avs you have uploaded).....
StainlessS
8th January 2017, 14:26
At a guess I'de say that you are using Avs+, and GScript is built-in in Avs+, if you are gonna use non-standard Avs, then you really do need to know
the pitfalls to expect and fix them yourself.
Remove the calls to GScript(""" and terminating """)
or the single quote versions where used. I'm not gonna do it for you, you need to be able to do it yourself.
EDIT: You will probably want to remove the LoadPlugin() for GScript too.
Bernardd
8th January 2017, 15:49
StainlessS
Thanks
Bernard
StainlessS
11th January 2017, 23:05
Big apologies to Mounir, The script was indeed flawed, please forgive my nonsense.
Here, modded script to try, however suggest Bernardd peruse it first:- http://www.mediafire.com/file/5tyfefna2l2pykj/RGBAdapt_awb_process.zip
Berny, I will probably NOT bother to try to decipher future renditions if you remove formatting (saves almost no execution time in doing so).
Here in the long,
RGBAdapt_awb_process.avs, post 1 of 2.
######
### RGBAdapt_Awb_Process.avs, RGB32 + YV12 ONLY.
######
AviSource("F:\v\StarWars.avi").ConvertToRGB32 #.Trim(10000,-1000)
/*
AVISource("C:\.............\your video.avi")
LoadPlugin("C:\............\GRunT.dll")
LoadPlugin("C:\............\GScript.dll")
LoadPlugin("C:\............\RGBAdapt.dll")
LoadPlugin("C:\............\RT_Stats26.dll")
*/
# display tunings
comparison = false
show_scrutinized = True
show_info = True
# color space matrix tuning and specify the source rectangle under scrutiny
matrix = "Rec601"
x = 0.02
Y = 0.02
w = 0.02
h = 0.02
#extreme pixels percentage to be ignored when datas extraction
threshold = 0.1
# automatic white balance preset tunings
threshold_auto = 128.0
gain_strength = 1.0
rpow_strength = 1.0
bias_strength = 1.0
# If you use AvsPmod user sliders you can delete comment for following lines
#~ [<separator="display tunings">]
#~ comparison = Select([<"show different settings - (false ou true) default = false = 0", 0, 1, 1>], false , true)
#~ show_scrutinized = Select([<"show scrutinized aera - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_info = Select([<"show datas - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ [<separator="color space matrix tuning">]
#~ matrix = Select([<"color matrix - (Rec 601= 0 ou Rec 709 =1) = default = 0", 0, 1, 0>], "Rec601" , "Rec709")
#~ [<separator=""specify the source rectangle under scrutiny and percentage extreme pixels to ignore">]
#~ x = [<"ignore pixels on left - width percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ Y= [<"ignore pixels on top - heigth percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ w = [<"ignore pixels on right - width percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ h = [<"ignore pixels on bottom - heigth percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ [<separator=""specify the extreme pixels percentage to be ignored when datas extraction">]
#~ threshold = [<"percentage for extreme pixels to be ignored - default : 0.10", 0.00, 1.00, 0.1>]
#~ [<separator="automatic white balance tunings">]
#~ threshold_auto = [<"threshold for enable cont process - default : 128.0", 0.0, 255.0, 128.0>]
#~ gain_strength = [<"gain strength - default : 1.0", 0.0, 1.0, 1.0>]
#~ rpow_strength = [<"rpow strength - default : 1.0", 0.0, 1.0, 1.0>]
#~ bias_strength = [<"final bias strength - default : 1.0", 0.0, 1.0, 1.0>]
#######
#######
#######
/*
# Without Stacked View capability
RGBAdapt_AWB_Process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h,
\ threshold=threshold,threshold_auto=threshold_auto,
\ gain_strength=gain_strength,rpow_strength=rpow_strength,bias_strength=bias_strength
\ )
*/
# With Stacked View capability
AWB_Func(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h,
\ threshold=threshold,threshold_auto=threshold_auto,
\ gain_strength=gain_strength,rpow_strength=rpow_strength,bias_strength=bias_strength,
\ Comparison=Comparison
\ )
Return Last
/*
#----------------------------------------------based on RGBADapt plugin --------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=170642 #
#-------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need RT_Stats plugin -----------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=165479 #
#-------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need GRunT plugin --------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=139337 #
#-------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need GScript plugin ------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=147846 #
#-------------------------------------------------------------------------------------------------------------------#
*/
Function RGBAdapt_AWB_Process(clip clip,string "matrix",bool "show_scrutinized",bool "show_info",float "x",float "y",float "w",float "h",
\ float "threshold", Float "threshold_auto", float "gain_strength", float "rpow_strength", float "bias_strength") {
# Clip MUST be YV12 or RGB32. Always returns SAME colorspace as input.
clip
myName="RGBAdapt_Awb_Process: "
Assert(RT_FunctionExist("RGBAdapt"),myName+"RGBAdapt plugin must be loaded, http://forum.doom9.org/showthread.php?t=170642")
Assert(RT_FunctionExist("GScriptClip"),myName+"GRunT plugin must be loaded, http://forum.doom9.org/showthread.php?t=139337")
Assert(RT_FunctionExist("GScript"),myName+"GScript plugin must be loaded, http://forum.doom9.org/showthread.php?t=147846")
Assert(IsYV12(clip) || IsRGB32(clip),RT_String("%sInput video colorspace must be YV12 or RGB32",myName))
matrix = Default(matrix, "Rec601") # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709",RT_String("%smatrix 'Rec601' or 'Rec709'('%s')",myName,matrix))
show_scrutinized = Default(show_scrutinized, false) # show scrutinized area or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.0)) # width percentage to specify coords source rectangle under scrutiny, the default : x=y=h=w=0.0 full frame
Assert(0.0 <= x <= 0.99,RT_String("%s0.0 <= x <= 0.99(%f)",myName,x))
y = float(Default(y,0.0)) # height percentage to specify coords source rectangle under scrutiny, the default : x=y=h=w=0.0 full frame
Assert(0.0 <= y <= 0.99,RT_String("%s0.0 <= y <= 0.99(%f)",myName,y))
w = float(Default(w,0.0)) # coords specify source rectangle under scrutiny, the default : x=y=h=w=0.0 is full frame
Assert(0.0 <= w <= 0.99,RT_String("%s0.0 <= w <= 0.99(%f)",myName,w))
Assert(0.0 <= (x+w) <= 0.99 ,RT_String("%s0.0 <= (x+w) <= 0.99(%f)",myName,x+w))
h = float(Default(h,0.0)) # coords specify source rectangle under scrutiny , the default : x=y=h=w=0.0 is full frame
Assert(0.0 <= h <= 0.99,RT_String("%s0.0 <= h <= 0.99(%f)",myName,h))
Assert(0.0 <= (y+h) <= 0.99 ,RT_String("%s0.0 <= (y+h) <= 0.99(%f)",myName,y+h))
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(0.0 <= threshold <= 1.0,RT_String("%s0.0 <= threshold <= 1.0(%f)",myName,threshold))
threshold_auto = Float(Default(threshold_auto, 128.0)) # threshold for enable cont process
Assert(0.0 <= threshold_auto <= 255.0,RT_String("%s0.0 <= threshold_auto <= 255.0(%f)",myName,threshold_auto))
gain_strength = Float(Default(gain_strength, 1.0)) # gain strength
Assert(0.0 <= gain_strength <= 1.0,RT_String("%s0.0 <= gain_strength <= 1.0(%f)",myName,gain_strength))
rpow_strength = Float(Default(rpow_strength, 1.0)) #rpow strength
Assert(0.0 <= rpow_strength <= 1.0,RT_String("%s0.0 <= rpow_strength <= 1.0(%f)",myName,rpow_strength))
bias_strength = Float(Default(bias_strength, 1.0)) #bias strength
Assert(0.0 <= bias_strength <= 1.0,RT_String("%s0.0 <= bias_strength <= 1.0(%f)",myName,bias_strength))
#---------- Specify the source rectangle under scrutiny, x,y,w,h are now type Int
x = int( Width * x)
y = int( Height * y)
w = int(-Width * w)
h = int(-Height * h)
#--------- RGB color space process
RGB32_clip = (!isRGB32(clip)) ? ConvertToRGB32(clip, matrix=matrix) : clip
CWID=69 CHIT=21 # display Width and Height in Subtitle characters
MinWid=CWID*10 MinHit=CHIT*20 # RT_Subtitle required width height in pixels (fixed font size is 10x20)
TooSmall=(Width<MinWid || Height<MinHit)
RedStr = (TooSmall) ? "Red values :\n" : "\a2Red values\a- :\n"
GrnStr = (TooSmall) ? "Green values :\n" : "\a4Green values\a- :\n"
BluStr = (TooSmall) ? "Blue values :\n" : "\a1Blue values\a- :\n"
# Use same string at each frame.
Fmt=
\ "\nChannels averages average : %7.3f\n" +
\ "Min max average diff : %7.3f : Contrast=%s\n\n" +
\ RedStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " R_bias=%7.3f : R_gain =%7.3f : R_cont =%.3f : R_rpow=%.3f\n\n" +
\ GrnStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " G_bias=%7.3f : G_gain =%7.3f : G_cont =%.3f : G_rpow=%.3f\n\n" +
\ BluStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " B_bias=%7.3f : B_gain =%7.3f : B_cont =%.3f : B_rpow=%.3f\n\n" +
\ "Channels averages average : %7.3f"
GSCript("""
# Nested Low level Function, Called per frame via GScriptClip(), RGB32 ONLY
Function RGBAdapt_awb_process_Lo(clip clp,String Fmt,bool show_info,int x,int y,int w,int h,float threshold,float threshold_auto,
\ float gain_strength, float rpow_strength,float bias_strength,Bool TooSmall,Int CWid,Int CHit) {
clp # Last = Input RGB32 clp clip.
# n = current_frame # n is current_frame, can use in RT_Stats to access frames relative to current. Not currently Used.
#---------- First pass : gain process for each channel
Last.RT_RgbChanStats(x=x,y=y,w=w,h=h,threshold=threshold,chan=-1,flgs= 1+2+4+16) # Using default 'RCS_' return Prefix
blank_clip = RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2
# Leave RCS_ values as original (avoid repeat function call in Show_info), new variables without RCS_ prefix, avoid div by zero.
MinMaxDiff_0 = Max(RCS_MinMaxDiff_0, 0.00001)
MinMaxDiff_1 = Max(RCS_MinMaxDiff_1, 0.00001)
MinMaxDiff_2 = Max(RCS_MinMaxDiff_2, 0.00001)
#---- gain args calculation
r_gain = 1.0+(255.0/MinMaxDiff_0-1.0)*gain_strength
r_gain_bias = -RCS_Min_0*r_gain*gain_strength
g_gain = 1.0+(255.0/MinMaxDiff_1-1.0)*gain_strength
g_gain_bias = -RCS_Min_1*g_gain*gain_strength
b_gain = 1.0+(255.0/MinMaxDiff_2-1.0)*gain_strength
b_gain_bias = -RCS_Min_2*b_gain*gain_strength
#------ contrast automatic enable
contrast = (Max(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2) - Min(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2) > threshold_auto)
# Cont is dangerous, because it can overshoot light and dark, but it is necessary to help to find good correction for very big
# color cast. Thus it is enable only for big color cast with a automatic weighted autocont strength based on my tests results.
# I observe that picture do'nt need contrast is picture, which have a large histogram, which have min value near 0 and
# max value near 255, which have bigger min max diff value.
if (contrast){
r_cont = 1.0 + (r_gain - 1.0) * (255.0 - RCS_MinMaxDiff_0)/255.0
r_cont_max = RCS_Max_0 * r_gain + r_gain_bias + (r_cont - 1) *(RCS_Max_0 - 128)
r_cont_bias = (255 - r_cont_max) * gain_strength
g_cont = 1.0 + (g_gain - 1.0) * (255.0 - RCS_MinMaxDiff_1)/255.0
g_cont_max = RCS_Max_1 * g_gain + g_gain_bias + (g_cont - 1) *(RCS_Max_1 - 128)
g_cont_bias = (255 - g_cont_max) * gain_strength
b_cont = 1.0 + (b_gain - 1.0) * (255.0 - RCS_MinMaxDiff_2)/255.0
b_cont_max = RCS_Max_2 * b_gain + b_gain_bias + (b_cont - 1) *(RCS_Max_2 - 128)
b_cont_bias = (255 - b_cont_max) * gain_strength
} else {
r_cont = 1.0 g_cont = 1.0 b_cont = 1.0
r_cont_bias = 0.0 g_cont_bias = 0.0 b_cont_bias = 0.0
}
StainlessS
11th January 2017, 23:07
Post 2, or 2.
r_bias=r_gain_bias+r_cont_bias g_bias=g_gain_bias+g_cont_bias b_bias=b_gain_bias+b_cont_bias
#----gamma args calculation in accordance with gray world theory
# In gray world theory, in YUV range, we increase or decrease average value to ref = 128.0, but in RGB range
# ref = average of channel average values is better.
# With contrast use, average of channel average value after gain process without cont process give a better picture light.
# In gamma process, to incresae or decrease average value, we use gamma args. To find this gamma args, we
# solve this equation ref = pow(average value/255.0,1/gamma args)
ref=(RCS_Ave_0*r_gain+r_gain_bias + RCS_Ave_1*g_gain+g_gain_bias + RCS_Ave_2*b_gain+b_gain_bias) / 3.0
r_rpow = 1 + (log((RCS_Ave_0 * r_gain + r_gain_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 + (log((RCS_Ave_1 * g_gain + g_gain_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 + (log((RCS_Ave_2 * b_gain + b_gain_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
b_rpow = Min (4.0, Max (b_rpow, 0.1))
#--------- bias gain cont in RGBadapt args range
r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))
r_gain = Min (8.0, Max (r_gain, -8.0)) g_gain = Min (8.0, Max (g_gain, -8.0)) b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0)) g_cont = Min (8.0, Max (g_cont, -8.0)) b_cont = Min (8.0, Max (b_cont, -8.0))
#---------- bias corrections in accordance with gray world theory
#----------- bias corrections extraction and calcul
# ssS, Create and measure temp clip
TempC=clp.RGBAdapt(R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow,
\ G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow,
\ B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow)
TempC.RT_RgbChanStats(x=x,y=y,w=w,h=h,threshold=threshold,chan=-1,flgs=16,Prefix="TMP_") ### Use TMP_ prefix HERE
# Ref for bias corrections always calculated with gain output, because is more light than calculated with gain cont & gamma output
dr = (ref - TMP_Ave_0)* bias_strength dg = (ref - TMP_Ave_1)* bias_strength db = (ref - TMP_Ave_2)* bias_strength
r_bias = (r_gain_bias + r_cont_bias + dr) g_bias = (g_gain_bias + g_cont_bias + dg) b_bias = (b_gain_bias + b_cont_bias + db)
r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))
#------------ AWB output with gain cont rpow and bias process
# now change for real
(blank_clip==0)
\ ? clp
\ : clp.RGBAdapt(R_bias=r_bias,R_Gain=r_gain,R_Cont=r_cont,R_rpow=r_rpow,
\ G_bias=g_bias,G_Gain=g_gain,G_Cont=g_cont,G_rpow=g_rpow,
\ B_bias=b_bias,B_Gain=b_gain,B_Cont=b_cont,B_rpow=b_rpow)
if(show_info) {
#--------- final RGB values extraction for display
# Use different 'FIN_' Prefix so as not to destroy original variables
Last.RT_RgbChanStats(x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16,Prefix="FIN_")
S=RT_String(Fmt,
\ (RCS_Ave_0+RCS_Ave_1+RCS_Ave_2)/3.0, Max(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2) - Min(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2),
\ contrast,
\
\ RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0,
\ FIN_Ave_0, FIN_MinMaxDiff_0, FIN_Min_0, FIN_Max_0,
\ r_bias, r_gain,r_cont,r_rpow,
\
\ RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1,
\ FIN_Ave_1, FIN_MinMaxDiff_1, FIN_Min_1, FIN_Max_1,
\ g_bias, g_gain,g_cont,g_rpow,
\
\ RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2,
\ FIN_Ave_2, FIN_MinMaxDiff_2, FIN_Min_2, FIN_Max_2,
\ b_bias,b_gain,b_cont,b_rpow,
\
\ (FIN_Ave_0 + FIN_Ave_1 + FIN_Ave_2 )/3,Esc=(TooSmall)?0:1)
(TooSmall)
\ ? Last.Subtitle(S,Font="Courier New",lsp=0,text_color=$FFFF00,halo_color=$0,size=height/float(CHIT),
\ Font_width=width/FloaT(CWID))
\ : Last.RT_Subtitle("%s",S)
} # End ShowInfo
Return Last
} # End, RGBAdapt_awb_process_Lo()
# GScriptClip, Calling Low level Function RGBAdapt_awb_process_Lo() at each frame.
# Named ARGS variables at current script level, are imported into GScriptClip script, and passed as args to RGBAdapt_awb_process_Lo().
ARGS="Fmt,show_info,x,y,w,h,threshold,threshold_auto,gain_strength,rpow_strength,bias_strength,TooSmall,CWid,CHit"
RGB32_clip.GScriptClip("RGBAdapt_awb_process_Lo(last,"+ARGS+")", local=true, args=ARGS)
# Do border outside of Scriptclip.
if(show_scrutinized) {
Level = 100 # 0 (Off) -> 257 (Full)
MarkColor = $00FF00
#-------- display scrutinized area
scrutinized_green = Last.BlankClip(width = Width-x+w, height = height-y+h, color=MarkColor)
scrutinized_mask = scrutinized_green.Blankclip(color=$0).LetterBox(2,2,2,2,$FFFFFF)
Layer(last,scrutinized_green.Mask(scrutinized_mask),x=x,y=y,level=Level)
} # End show_scrutinized
""")
Return (clip.isYV12) ? ConvertToYV12(last, matrix=matrix) : last # Return original colorspace, YV12 or RGB32
}
Function AWB_Func(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h",
\ float "threshold",float "threshold_auto",float "gain_strength",float "rpow_strength",float "bias_strength",Bool "Comparison") {
# Clip MUST be YV12 or RGB32. Always returns SAME colorspace as input.
Gscript("""
clip
output=clip.RGBAdapt_Awb_Process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,x=x,y=y,w=w,h=h,threshold=threshold,
\ gain_strength=gain_strength, rpow_strength=rpow_strength, bias_strength=bias_strength,threshold_auto=threshold_auto)
if (!Default(Comparison,false)) {
output
} else {
# Here, Clip is either RGB32 or YV12.
# Ensure RGB32 for all calls to RGBAdapt_Awb_Process (Only convert input at most once)
RGB_Clip = (Clip.IsYV12) ? clip.ConvertToRGB32(matrix=matrix) : clip
without_contrast = RGB_Clip.RGBAdapt_awb_process(matrix=matrix, show_scrutinized=show_scrutinized, show_info=show_info,
\ x=x, y=y, w=w, h=h,threshold_auto=255.0)
with_contrast = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized, show_info=show_info,
\ x=x,y=y,w=w,h=h,threshold_auto=0.0)
gain_rpow = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h, threshold_auto=threshold_auto,bias_strength=0.0)
gain_bias = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h, threshold_auto=threshold_auto,rpow_strength=0.0)
only_gain = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h, threshold=0.1,threshold_auto=threshold_auto,rpow_strength=0.0,bias_strength=0.0)
YV12_Clip = (clip.IsRGB32) ? clip.ConvertToYV12(matrix=matrix) : clip
colorYUV_AWB = YV12_Clip.ColorYUV(autowhite = true)
# Convert clips to original Input ColorSpace.
if(clip.IsRGB32) {
colorYUV_AWB = colorYUV_AWB.ConvertToRGB32(matrix=matrix)
} else {
without_contrast = without_contrast.ConvertToYV12(matrix=matrix)
with_contrast = with_contrast.ConvertToYV12(matrix=matrix)
gain_rpow = gain_rpow.ConvertToYV12(matrix=matrix)
gain_bias = gain_bias.ConvertToYV12(matrix=matrix)
only_gain = only_gain.ConvertToYV12(matrix=matrix)
}
contrast_label=(threshold_auto==255.0) ? "without contrast"
\ : (threshold_auto==0.0) ? "with contrast"
\ : "contrast in accordance with threshold"
STK1 = StackHorizontal(
\ clip.blankclip.AddBorders(0,20,0,0,color=$0),
\ without_contrast.AddBorders(0,20,0,0,color=$0).Subtitle("gain rpow and bias process without contrast"),
\ with_contrast.AddBorders(0,20,0,0,color=$0).Subtitle("gain rpow and bias process with contrast")
\ )
STK2 = StackHorizontal(
\ clip.AddBorders(0,0,0,20,color=$0).Subtitle("original", y = clip.height),
\ colorYUV_AWB.AddBorders(0,0,0,20,color=$0).Subtitle("As a reminder, classical ColorYUV awb", y = clip.height),
\ output.AddBorders(0,0,0,20,color=$0).Subtitle ("Selected output"+ " " +contrast_label, y = clip.height)
\ )
STK3 = StackHorizontal(
\ only_gain.AddBorders(0,0,0,20,color=$0).Subtitle("only gain "+ " " +contrast_label, y = clip.height),
\ gain_bias.AddBorders(0,0,0,20,color=$0).Subtitle("only gain and bias"+ " " +contrast_label, y = clip.height),
\ gain_rpow.AddBorders(0,0,0,20,color=$0).Subtitle("only gain and rpow"+ " " +contrast_label, y = clip.height)
\ )
StackVertical(STK1,STK2,STK3)
} # End, if
""") # End GScript
Return Last # Return Original ColorSpace
}
EDIT:RGB24, no longer an option, gotta have some rules, somewhere and some guarantees.
EDIT:, was thinkin' that my coffee was looking a bit dark, so put some milk in it, turned out was OXO (Beef-tea or whatever),
not too bad with a bit of milk (but might have preferred without).
Bernardd
20th January 2017, 11:31
Hello StainlessS
I'm sorry, my answer is late because I was traveling.
First thank you.
Secondly, for my instruction, where was the bug in my script?
Third, I have now understood your script drafting plan and noted the editors to preserve the variables. I therefore approve your version, which is promised, I will keep the architecture if I had to modify in the future the calculations of white balance.
The script attempts to eliminate dominant colors, with two approaches.
The first with a gain whose objective is to spread the spectrum of each channel between 0 and 255. The light is thus bleached and the shadow blackened.
The second is to apply the gray world theory with a gamma correction followed by a bias correction, instead of a simple bias correction.
But some people may think that the use of gamma to make a correction according to gray world theory is abusive. They can therefore configure the script to not use the gamma. Therefore, at the bottom of the comparison view, I planned the three displays of the main alternate combinations, in order to allow them to quickly measure the benefit of using the gamma.
As it is three bottom display are alternatives to the top combination, it seems to me that a green line makes it better to realize that this is not the default configuration.
I propose to modify the fourth line before the end of the script as follows:
StackVertical(STK1,STK2,STK3.Letterbox(20, 0, x1=0, x2=0, color=$00FF00).Subtitle( "Perhaps other good combinations ?",align = 8))
Finally, I remind that for the very dominant colors the use of contrast is necessary and that for me the combination by default gives, in this case, the best result.
https://www.dropbox.com/s/3zazchlvm3f8cw1/StainlessS%20script%20version.png?dl=0
Thanks
Bernard
PS I have used google translate
StainlessS
20th January 2017, 13:35
Bug, well not 100% sure but think was related to colorspace..
Think was accepting any rgb and returning a specific rgb and so
Input and output colorspace not necessarily the same.
Anyway,, forced rgb32 only, and a requirement as we changed to using layer rather than overlay (quicker).
Mobile.
Bernardd
18th February 2017, 17:48
Hello StainlessS
The mathematical white balance automatic gives quite often a result with neutral tones, without heat, so here is a new version with the addition of a function of color temperature adjustment.
The principle is simple, a warm gray is a gray with 6% yellow, a cold gray is a gray with 6% blue. https://en.wikipedia.org/wiki/Color_temperature
The new function can therefore add a maximum of 6% of yellow or blue to the reference value used to calculate the bias for the rpow and final bias corrections.
This new function can be manual or automatic.
My tests showed me that 6% of yellow is often excessive, but that 2 or 3% can make a picture more pleasant (according to my taste) without excessively balancing the white balance.
Moreover, with this function, it is possible to quickly adjust the appearance of the green.
Having the objective of having a fully automatic white balance, I have provided an automatic adjustment of the color temperature. The idea is that the stronger the color correction, the more the mathematical white balance will give a neutral result. The increase in temperature is therefore proportional to the greater bias correction observed for the red or blue channels. This simplistic method generally gives acceptable results. But obviously can not replace the intelligent analysis of the scene by the operator, who can accurately estimate the need to change the color temperature.
On the comparison display, the two images at the top right never receive color temperature correction. The four middle and bottom right images are affected by the color temperature correction selection.
Finally, I made small changes to details
CWID = 72 CHIT = 24 instead of 69 and 21
Min max with diff (for auto contrast tune) instead of Min max average diff
The script is in the two following posts.
Bernard
Bernardd
18th February 2017, 17:55
Script part 1
######
### RGBAdapt_Awb_Process.avs, RGB32 + YV12 ONLY.
######
#~ AviSource("F:\v\StarWars.avi").ConvertToRGB32 #.Trim(10000,-1000)
/*
AVISource("C:\.............\your video.avi")
LoadPlugin("C:\............\GRunT.dll")
LoadPlugin("C:\............\GScript.dll")
LoadPlugin("C:\............\RGBAdapt.dll")
LoadPlugin("C:\............\RT_Stats26.dll")
*/
# display tunings
comparison = false
show_scrutinized = True
show_info = True
# color space matrix tuning and specify the source rectangle under scrutiny
matrix = "Rec601"
x = 0.02
Y = 0.02
w = 0.02
h = 0.02
#extreme pixels percentage to be ignored when datas extraction
threshold = 0.1
# automatic white balance preset tunings
threshold_auto = 128.0
gain_strength = 1.0
rpow_strength = 1.0
bias_strength = 1.0
auto_temperature = true
temperature = 0.3
# If you use AvsPmod user sliders you can delete comment for following lines
#~ [<separator="display tunings">]
#~ comparison = Select([<"show different settings - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_scrutinized = Select([<"show scrutinized aera - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_info = Select([<"show datas - (false ou true) default = false = 0", 0, 1, 1>], false , true)
#~ [<separator="color space matrix tuning">]
#~ matrix = Select([<"color matrix - (Rec 601= 0 ou Rec 709 =1) = default = 0", 0, 1, 0>], "Rec601" , "Rec709")
#~ [<separator=""specify the source rectangle under scrutiny and percentage extreme pixels to ignore">]
#~ x = [<"ignore pixels on left - width percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ Y= [<"ignore pixels on top - heigth percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ w = [<"ignore pixels on right - width percentage - default : 0.00", 0.00, 0.99, 0.11>]
#~ h = [<"ignore pixels on bottom - heigth percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ [<separator=""specify the extreme pixels percentage to be ignored when datas extraction">]
#~ threshold = [<"percentage for extreme pixels to be ignored - default : 0.10", 0.00, 1.00, 0.1>]
#~ [<separator="automatic white balance tunings">]
#~ threshold_auto = [<"threshold for enable cont process - default : 128.0", 0.0, 255.0, 128.0>]
#~ gain_strength = [<"gain strength - default : 1.0", 0.0, 1.0, 1.0>]
#~ rpow_strength = [<"rpow strength - default : 1.0", 0.0, 1.0, 1.0>]
#~ bias_strength = [<"final bias strength - default : 1.0", 0.0, 1.0, 0.0>]
#~ [<separator="color temperature tunings">]
#~ auto_temperature = Select([<"automatic color temperature - (false ou true) default = true = 1", 0, 1, 0>], false , true)
#~ temperature = [<"manual color temperature - default : 0.0", -1.0, 1.0, 0.0>]
#######
#######
#######
/*
# Without Stacked View capability
RGBAdapt_AWB_Process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h,
\ threshold=threshold,threshold_auto=threshold_auto,
\ gain_strength=gain_strength,rpow_strength=rpow_strength,bias_strength=bias_strength,
\ auto_temperature = auto_temperature, temperature = temperature)
*/
# With Stacked View capability
AWB_Func(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h,
\ threshold=threshold,threshold_auto=threshold_auto,
\ gain_strength=gain_strength,rpow_strength=rpow_strength,bias_strength=bias_strength,
\ auto_temperature = auto_temperature, temperature = temperature,
\ Comparison=Comparison)
Return Last
/*
#----------------------------------------------based on RGBADapt plugin --------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=170642 #
#-------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need RT_Stats plugin -----------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=165479 #
#-------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need GRunT plugin --------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=139337 #
#-------------------------------------------------------------------------------------------------------------------#
#---------------------------------------------- need GScript plugin ------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=147846 #
#-------------------------------------------------------------------------------------------------------------------#
*/
Function RGBAdapt_AWB_Process(clip clip,string "matrix",bool "show_scrutinized",bool "show_info",float "x",float "y",float "w",float "h",
\ float "threshold", Float "threshold_auto", float "gain_strength", float "rpow_strength", float "bias_strength",
\ bool "auto_temperature", float "temperature") {
# Clip MUST be YV12 or RGB32. Always returns SAME colorspace as input.
clip
myName="RGBAdapt_Awb_Process: "
Assert(RT_FunctionExist("RGBAdapt"),myName+"RGBAdapt plugin must be loaded, http://forum.doom9.org/showthread.php?t=170642")
Assert(RT_FunctionExist("GScriptClip"),myName+"GRunT plugin must be loaded, http://forum.doom9.org/showthread.php?t=139337")
Assert(RT_FunctionExist("GScript"),myName+"GScript plugin must be loaded, http://forum.doom9.org/showthread.php?t=147846")
Assert(IsYV12(clip) || IsRGB32(clip),RT_String("%sInput video colorspace must be YV12 or RGB32",myName))
matrix = Default(matrix, "Rec601") # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709",RT_String("%smatrix 'Rec601' or 'Rec709'('%s')",myName,matrix))
show_scrutinized = Default(show_scrutinized, false) # show scrutinized area or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.0)) # width percentage to specify coords source rectangle under scrutiny, the default : x=y=h=w=0.0 full frame
Assert(0.0 <= x <= 0.99,RT_String("%s0.0 <= x <= 0.99(%f)",myName,x))
y = float(Default(y,0.0)) # height percentage to specify coords source rectangle under scrutiny, the default : x=y=h=w=0.0 full frame
Assert(0.0 <= y <= 0.99,RT_String("%s0.0 <= y <= 0.99(%f)",myName,y))
w = float(Default(w,0.0)) # coords specify source rectangle under scrutiny, the default : x=y=h=w=0.0 is full frame
Assert(0.0 <= w <= 0.99,RT_String("%s0.0 <= w <= 0.99(%f)",myName,w))
Assert(0.0 <= (x+w) <= 0.99 ,RT_String("%s0.0 <= (x+w) <= 0.99(%f)",myName,x+w))
h = float(Default(h,0.0)) # coords specify source rectangle under scrutiny , the default : x=y=h=w=0.0 is full frame
Assert(0.0 <= h <= 0.99,RT_String("%s0.0 <= h <= 0.99(%f)",myName,h))
Assert(0.0 <= (y+h) <= 0.99 ,RT_String("%s0.0 <= (y+h) <= 0.99(%f)",myName,y+h))
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(0.0 <= threshold <= 1.0,RT_String("%s0.0 <= threshold <= 1.0(%f)",myName,threshold))
threshold_auto = Float(Default(threshold_auto, 128.0)) # threshold for enable cont process
Assert(0.0 <= threshold_auto <= 255.0,RT_String("%s0.0 <= threshold_auto <= 255.0(%f)",myName,threshold_auto))
gain_strength = Float(Default(gain_strength, 1.0)) # gain strength
Assert(0.0 <= gain_strength <= 1.0,RT_String("%s0.0 <= gain_strength <= 1.0(%f)",myName,gain_strength))
rpow_strength = Float(Default(rpow_strength, 1.0)) #rpow strength
Assert(0.0 <= rpow_strength <= 1.0,RT_String("%s0.0 <= rpow_strength <= 1.0(%f)",myName,rpow_strength))
bias_strength = Float(Default(bias_strength, 1.0)) #bias strength
Assert(0.0 <= bias_strength <= 1.0,RT_String("%s0.0 <= bias_strength <= 1.0(%f)",myName,bias_strength))
auto_temperature = Default(auto_temperature, true) # enable automatic color temperature factor, default true
temperature = Float(Default(temperature, 0.0)) # manual color temperature factor
Assert(- 1.0 <= temperature <= 1.0,RT_String("%s-1.0 <= temperature <= 1.0(%f)",myName,temperature))
#---------- Specify the source rectangle under scrutiny, x,y,w,h are now type Int
x = int( Width * x)
y = int( Height * y)
w = int(-Width * w)
h = int(-Height * h)
#--------- RGB color space process
RGB32_clip = (!isRGB32(clip)) ? ConvertToRGB32(clip, matrix=matrix) : clip
CWID=72 CHIT=24 #69 21 # display Width and Height in Subtitle characters
MinWid=CWID*10 MinHit=CHIT*20 # RT_Subtitle required width height in pixels (fixed font size is 10x20)
TooSmall=(Width<MinWid || Height<MinHit)
RedStr = (TooSmall) ? "Red values :\n" : "\a2Red values\a- :\n"
GrnStr = (TooSmall) ? "Green values :\n" : "\a4Green values\a- :\n"
BluStr = (TooSmall) ? "Blue values :\n" : "\a1Blue values\a- :\n"
# Use same string at each frame.
Fmt=
\ "\nChannels averages average : %7.3f\n" +
\ "Min max ave diff (for auto contrast tune) : %7.3f : Contrast=%s\n\n" +
\ RedStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " R_bias=%7.3f : R_gain =%7.3f : R_cont =%.3f : R_rpow=%.3f\n\n" +
\ GrnStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " G_bias=%7.3f : G_gain =%7.3f : G_cont =%.3f : G_rpow=%.3f\n\n" +
\ BluStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " B_bias=%7.3f : B_gain =%7.3f : B_cont =%.3f : B_rpow=%.3f\n\n" +
\ "Channels averages average : %7.3f \n\nColor temperature mod = %.1f percent of %s (max 6.0 percent)"
GSCript("""
# Nested Low level Function, Called per frame via GScriptClip(), RGB32 ONLY
Function RGBAdapt_awb_process_Lo(clip clp,String Fmt,bool show_info,int x,int y,int w,int h,float threshold,float threshold_auto,
\ float gain_strength, float rpow_strength,float bias_strength,Bool TooSmall,Int CWid,Int CHit,
\ bool auto_temperature, float temperature) {
clp # Last = Input RGB32 clp clip.
# n = current_frame # n is current_frame, can use in RT_Stats to access frames relative to current. Not currently Used.
#---------- First pass : gain process for each channel
Last.RT_RgbChanStats(x=x,y=y,w=w,h=h,threshold=threshold,chan=-1,flgs= 1+2+4+16) # Using default 'RCS_' return Prefix
blank_clip = RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2
# Leave RCS_ values as original (avoid repeat function call in Show_info), new variables without RCS_ prefix, avoid div by zero.
MinMaxDiff_0 = Max(RCS_MinMaxDiff_0, 0.00001)
MinMaxDiff_1 = Max(RCS_MinMaxDiff_1, 0.00001)
MinMaxDiff_2 = Max(RCS_MinMaxDiff_2, 0.00001)
#---- gain args calculation
r_gain = 1.0 + (255.0/MinMaxDiff_0 - 1.0) * gain_strength
r_gain_bias = -RCS_Min_0 * r_gain *gain_strength
g_gain = 1.0 + (255.0/MinMaxDiff_1 - 1.0) * gain_strength
g_gain_bias = -RCS_Min_1 * g_gain * gain_strength
b_gain = 1.0 + (255.0/MinMaxDiff_2 - 1.0) * gain_strength
b_gain_bias = -RCS_Min_2 * b_gain * gain_strength
#------ contrast automatic enable
contrast = (Max(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2) - Min(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2) > threshold_auto)
# Cont is dangerous, because it can overshoot light and dark, but it is necessary to help to find good correction for very big
# color cast. Thus it is enable only for big color cast with a automatic weighted autocont strength based on my tests results.
# I observe that picture do'nt need contrast is picture, which have a large histogram, which have min value near 0 and
# max value near 255, which have bigger min max diff value.
if (contrast){
r_cont = 1.0 + (r_gain - 1.0) * (255.0 - RCS_MinMaxDiff_0)/255.0
r_cont_max = RCS_Max_0 * r_gain + r_gain_bias + (r_cont - 1) *(RCS_Max_0 - 128)
r_cont_bias = (255 - r_cont_max) * gain_strength
g_cont = 1.0 + (g_gain - 1.0) * (255.0 - RCS_MinMaxDiff_1)/255.0
g_cont_max = RCS_Max_1 * g_gain + g_gain_bias + (g_cont - 1) *(RCS_Max_1 - 128)
g_cont_bias = (255 - g_cont_max) * gain_strength
b_cont = 1.0 + (b_gain - 1.0) * (255.0 - RCS_MinMaxDiff_2)/255.0
b_cont_max = RCS_Max_2 * b_gain + b_gain_bias + (b_cont - 1) *(RCS_Max_2 - 128)
b_cont_bias = (255 - b_cont_max) * gain_strength
} else {
r_cont = 1.0 g_cont = 1.0 b_cont = 1.0
r_cont_bias = 0.0 g_cont_bias = 0.0 b_cont_bias = 0.0
}
r_bias = r_gain_bias +r_cont_bias g_bias = g_gain_bias +g_cont_bias b_bias = b_gain_bias + b_cont_bias
Bernardd
18th February 2017, 17:57
Script part 2
#----gamma args calculation in accordance with gray world theory
# In gray world theory, in YUV range, we increase or decrease average value to ref = 128.0, but in RGB range
# ref = average of channel average values is better.
# With contrast use, average of channel average value after gain process without cont process give a better picture light.
# In gamma process, to incresae or decrease average value, we use gamma args. To find this gamma args, we
# solve this equation ref = pow(average value/255.0,1/gamma args)
ref = (RCS_Ave_0 * r_gain + r_gain_bias + RCS_Ave_1 * g_gain + g_gain_bias + RCS_Ave_2 * b_gain + b_gain_bias)/3.0
# Warm temperature = gray mixed with 6% yellow. Cool temperature = gray mixed with 6% blue. (https://en.wikipedia.org/wiki/Color_temperature)
# thus with temperature factor, you can adjust color temperature in manual or automatic mode.
if (auto_temperature) {
temperature = (ref - Min(RCS_Ave_0, RCS_Ave_2))/ref} # else temperature = manual temperature args
#~ add_color = (temperature >= 0) ? "yellow" : "blue" # this variable is only for display
r_rpow = 1 + (log((RCS_Ave_0 * r_gain + r_gain_bias)/255.0)/log(ref * (1 + 0.06 * temperature)/255.0) - 1) * rpow_strength
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 + (log((RCS_Ave_1 * g_gain + g_gain_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 + (log((RCS_Ave_2 * b_gain + b_gain_bias)/255.0)/log(ref * (1 - 0.06 * temperature)/255.0) - 1) * rpow_strength
b_rpow = Min (4.0, Max (b_rpow, 0.1))
#--------- bias gain cont in RGBadapt args range
r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))
r_gain = Min (8.0, Max (r_gain, -8.0)) g_gain = Min (8.0, Max (g_gain, -8.0)) b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0)) g_cont = Min (8.0, Max (g_cont, -8.0)) b_cont = Min (8.0, Max (b_cont, -8.0))
#---------- bias corrections in accordance with gray world theory
#----------- bias corrections extraction and calcul
# ssS, Create and measure temp clip
TempC=clp.RGBAdapt(R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow,
\ G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow,
\ B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow)
TempC.RT_RgbChanStats(x=x,y=y,w=w,h=h,threshold=threshold,chan=-1,flgs=16,Prefix="TMP_") ### Use TMP_ prefix HERE
# Ref for bias corrections always calculated with gain output, because is more light than calculated with new extracted channels average values
dr = (ref * (1 + 0.06 * temperature) - TMP_Ave_0) * bias_strength dg = (ref - TMP_Ave_1) * bias_strength
db = (ref * (1 - 0.06 * temperature) - TMP_Ave_2) * bias_strength
r_bias = (r_gain_bias + r_cont_bias + dr) g_bias = (g_gain_bias + g_cont_bias + dg) b_bias = (b_gain_bias + b_cont_bias + db)
r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))
#------------ AWB output with gain cont rpow and bias process
# now change for real
(blank_clip==0)
\ ? clp
\ : clp.RGBAdapt(R_bias=r_bias,R_Gain=r_gain,R_Cont=r_cont,R_rpow=r_rpow,
\ G_bias=g_bias,G_Gain=g_gain,G_Cont=g_cont,G_rpow=g_rpow,
\ B_bias=b_bias,B_Gain=b_gain,B_Cont=b_cont,B_rpow=b_rpow)
if(show_info) {
#--------- final RGB values extraction for display
# Use different 'FIN_' Prefix so as not to destroy original variables
add_color = (temperature >= 0) ? "yellow" : "blue" # this variable is only for display
Last.RT_RgbChanStats(x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16,Prefix="FIN_")
S=RT_String(Fmt,
\ (RCS_Ave_0+RCS_Ave_1+RCS_Ave_2)/3.0, Max(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2) - Min(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2),
\ contrast,
\
\ RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0,
\ FIN_Ave_0, FIN_MinMaxDiff_0, FIN_Min_0, FIN_Max_0,
\ r_bias, r_gain,r_cont,r_rpow,
\
\ RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1,
\ FIN_Ave_1, FIN_MinMaxDiff_1, FIN_Min_1, FIN_Max_1,
\ g_bias, g_gain,g_cont,g_rpow,
\
\ RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2,
\ FIN_Ave_2, FIN_MinMaxDiff_2, FIN_Min_2, FIN_Max_2,
\ b_bias,b_gain,b_cont,b_rpow,
\
\ (FIN_Ave_0 + FIN_Ave_1 + FIN_Ave_2 )/3, temperature*0.06*100,add_color, Esc=(TooSmall)?0:1)
(TooSmall)
\ ? Last.Subtitle(S,Font="Courier New",lsp=0,text_color=$FFFF00,halo_color=$0,size=height/float(CHIT),
\ Font_width=width/FloaT(CWID))
\ : Last.RT_Subtitle("%s",S)
} # End ShowInfo
Return Last
} # End, RGBAdapt_awb_process_Lo()
# GScriptClip, Calling Low level Function RGBAdapt_awb_process_Lo() at each frame.
# Named ARGS variables at current script level, are imported into GScriptClip script, and passed as args to RGBAdapt_awb_process_Lo().
ARGS="Fmt,show_info,x,y,w,h,threshold,threshold_auto,gain_strength,rpow_strength,bias_strength,TooSmall,CWid,CHit," +
"auto_temperature, temperature"
RGB32_clip.GScriptClip("RGBAdapt_awb_process_Lo(last,"+ARGS+")", local=true, args=ARGS)
# Do border outside of Scriptclip.
if(show_scrutinized) {
Level = 100 # 0 (Off) -> 257 (Full)
MarkColor = $00FF00
#-------- display scrutinized area
scrutinized_green = Last.BlankClip(width = Width-x+w, height = height-y+h, color=MarkColor)
scrutinized_mask = scrutinized_green.Blankclip(color=$0).LetterBox(2,2,2,2,$FFFFFF)
Layer(last,scrutinized_green.Mask(scrutinized_mask),x=x,y=y,level=Level)
} # End show_scrutinized
""")
Return (clip.isYV12) ? ConvertToYV12(last, matrix=matrix) : last # Return original colorspace, YV12 or RGB32
}
Function AWB_Func(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h",
\ float "threshold",float "threshold_auto",float "gain_strength",float "rpow_strength",float "bias_strength",Bool "Comparison",
\ bool "auto_temperature", float "temperature") {
# Clip MUST be YV12 or RGB32. Always returns SAME colorspace as input.
Gscript("""
clip
output=clip.RGBAdapt_Awb_Process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,x=x,y=y,w=w,h=h,threshold=threshold,
\ gain_strength=gain_strength, rpow_strength=rpow_strength, bias_strength=bias_strength,threshold_auto=threshold_auto,
\ auto_temperature = auto_temperature, temperature = temperature)
if (!Default(Comparison,false)) {
output
} else {
# Here, Clip is either RGB32 or YV12.
# Ensure RGB32 for all calls to RGBAdapt_Awb_Process (Only convert input at most once)
RGB_Clip = (Clip.IsYV12) ? clip.ConvertToRGB32(matrix=matrix) : clip
without_contrast = RGB_Clip.RGBAdapt_awb_process(matrix=matrix, show_scrutinized=show_scrutinized, show_info=show_info,
\ x=x, y=y, w=w, h=h,threshold_auto=255.0,auto_temperature = false, temperature = 0.0)
with_contrast = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized, show_info=show_info,
\ x=x,y=y,w=w,h=h,threshold_auto=0.0,auto_temperature = false,temperature = 0.0)
gain_rpow = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h, threshold_auto=threshold_auto,bias_strength=0.0,temperature = temperature)
gain_bias = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h, threshold_auto=threshold_auto,rpow_strength=0.0,temperature = temperature)
only_gain = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h, threshold=0.1,threshold_auto=threshold_auto,rpow_strength=0.0,bias_strength=0.0,temperature = temperature)
YV12_Clip = (clip.IsRGB32) ? clip.ConvertToYV12(matrix=matrix) : clip
colorYUV_AWB = YV12_Clip.ColorYUV(autowhite = true)
# Convert clips to original Input ColorSpace.
if(clip.IsRGB32) {
colorYUV_AWB = colorYUV_AWB.ConvertToRGB32(matrix=matrix)
} else {
without_contrast = without_contrast.ConvertToYV12(matrix=matrix)
with_contrast = with_contrast.ConvertToYV12(matrix=matrix)
gain_rpow = gain_rpow.ConvertToYV12(matrix=matrix)
gain_bias = gain_bias.ConvertToYV12(matrix=matrix)
only_gain = only_gain.ConvertToYV12(matrix=matrix)
}
contrast_label=(threshold_auto==255.0) ? "without contrast"
\ : (threshold_auto==0.0) ? "with contrast"
\ : "contrast in accordance with threshold"
STK1 = StackHorizontal(
\ clip.blankclip.AddBorders(0,20,0,0,color=$0),
\ without_contrast.AddBorders(0,20,0,0,color=$0).Subtitle("gain rpow and bias process without contrast"),
\ with_contrast.AddBorders(0,20,0,0,color=$0).Subtitle("gain rpow and bias process with contrast")
\ )
STK2 = StackHorizontal(
\ clip.AddBorders(0,0,0,20,color=$0).Subtitle("original", y = clip.height),
\ colorYUV_AWB.AddBorders(0,0,0,20,color=$0).Subtitle("As a reminder, classical ColorYUV awb", y = clip.height),
\ output.AddBorders(0,0,0,20,color=$0).Subtitle ("Selected output"+ " " +contrast_label, y = clip.height)
\ )
STK3 = StackHorizontal(
\ only_gain.AddBorders(0,0,0,20,color=$0).Subtitle("only gain "+ " " +contrast_label, y = clip.height),
\ gain_bias.AddBorders(0,0,0,20,color=$0).Subtitle("only gain and bias"+ " " +contrast_label, y = clip.height),
\ gain_rpow.AddBorders(0,0,0,20,color=$0).Subtitle("only gain and rpow"+ " " +contrast_label, y = clip.height)
\ )
StackVertical(STK1,STK2,STK3.Letterbox(20, 0, x1=0, x2=0, color=$00FF00).Subtitle( "Perhaps other good combinations ?",align = 8))
} # End, if
""") # End GScript
Return Last # Return Original ColorSpace
}
Bernardd
27th February 2017, 17:50
@wdwms:
Here your River country video processed by the script in the two posts before, followed by Tweak (hue = -10.0) for more blue water pool. It is not better white balance, it is just a another but automatic white balance.
https://youtu.be/F2E9gKd_o6c
Bernard
StainlessS
6th December 2018, 14:56
RgbAdapt v0.05, new version see 1st post.
dll's for avs v2.58, v2.60/+ x86, avs+ x64. Requires VS 2008 CPP Runtimes.
v0.1, fixed float to double conversion (0.1 -> 0.999999 etc)
v0.2, Copies RGB32 Alpha channel rather than zero.
v0.3, Added Imin,OMin, IMax and OMax args.
v0.4, Added RGBAdapt16(). (stack 16 output)
v0.5, Added version Resource, moved to VS 2008, with x64 added.
StainlessS
2nd March 2019, 00:28
RgbAdapt, no version bump, but zip re-dated todays date, with update for RgbAdapt_Graffer only.
Updated text
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.
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
\ )
"""
See first post.
EDIT: For clipboard data written via RgbAdapt_Graffer(), only non default args are written, so if all are defaults, will only write "RgbAdapt()".
EDIT: Added missing Commas [,] in red above.
Bernardd
2nd March 2019, 16:34
Hi StainlessS
In format description, i have added five commas in end, because whitout, this RGBAdapt Graffer error message is displayed "Excepting 33 RGBAdapt args, got 28".
Thus i use this script lines. And first try.
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,
\ 0, 0, 255, 255,
\ 0, 0, 255, 255,
\ 0, 0, 255, 255
\ )
Thus for example the string paste in clipboard is
RgbAdapt(-100.045639,1.255309,1.470780,0.328575,1.029997,0.457690,False,35.487328,1.197245,1.363713,1.527946,0.987434,0.694048,False,76.985939,1.541412,1.998344,1.795371,0.983234,0.652867,False,0,0,255,255,0,0,255,255,0,0,255,255)
But with this clipboard string, this RGBAdapt Graffer error message is displayed "Error getting text from clipboard"
Second try.
I have exported to clipboard a RGBAdapt Graffer tune like this sample RgbAdapt(R_Bias=206,5,R_Spow=2,111)
I have tryed to import this clipboard datas in RGBadapt Graffer, this RGBAdapt Graffer error message is displayed "Excepting 33 RGBAdapt args, got 4"
Perhaps is decimal notation problem, in french, my computer setting is ",", but for Avisynth is "."
Third try
I have written this short script
LoadPlugin("C:\....\RgbAdapt_x86.dll")
AViSource("c:\video.avi")ConvertToRGB32()
RgbAdapt(-100.045639,1.255309,1.470780,0.328575,1.029997,0.457690,False,35.487328,1.197245,1.363713,1.527946,0.987434,0.694048,False,76.985939,1.541412,1.998344,1.795371,0.983234,0.652867,False,0,0,255,255,0,0,255,255,0,0,255,255)
Now with the previous clipboard text, it works perfect.
Conclusion
I think decimal notation problem with french computer setting.
Do you agree ?
StainlessS
3rd March 2019, 06:22
Perhaps is decimal notation problem, in french, my computer setting is ",", but for Avisynth is "."
Yep that was it, fixed. See MediaFire.
Beats me how foreigners can put up with that nonsense, no wonder you are all confused. :)
EDIT: Note, Graffer output to clipboard will not be read back from clipboard, the two formats are different, write to CB only writes named arguments which are non default,
whereas read from clipboard expects every (UN-NAMED) arg and ALL in default order.
I could only mod this if I DO NOT write named args to clipboard and write ALL of them.
Bernardd
3rd March 2019, 20:44
Thanks you.
Now it run fine. I have only add the five commas.
Not a problem, but curious, the color correction of the same picture is not exactly the same in RGBAdapt graffer preview and in Avisynth RGBAdapt plugin output for the same args.
Thanks you.
StainlessS
4th March 2019, 02:37
What 5 commas ? you mean this lot (should be given as below, ie IMin,OMin,IMax,OMax, for each channel.)
\ 0, 0, 255, 255,
\ 0, 0, 255, 255,
\ 0, 0, 255, 255
If so, then I suggest you actuall add the default values as above, as if I do further parse string in future, will not break you script.
Also, not sure what would happen if the above 255 values are interpreted as 0 (which they would be, " ," interpreted as 0).
Also note, slider positions (and stuff) in the grapher are of limited resolution (eg for Bias, max res is -512 -> +512 in steps of 0.1), input args are rounded to that resolution.
Bernardd
4th March 2019, 16:37
In post #162, i have five commas in red. This commas are missing in post #161 and in RGBAdapt_ReadMe.txt.
But it is not a real problem, because with your RGBAdapt_Graffer error messages, it is easy to find this mistake.
Thanks, clipboard use is a good idea. Now it is easy to see color histogram.
StainlessS
4th March 2019, 17:02
In post #162, i have five commas in red.
I see what you mean now, sorry bout that :)
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.