Log in

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


Pages : 1 2 3 [4]

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 :)