View Full Version : RGBAdapt v0.5 plugin 06 Dec 2018
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
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.