Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 11th March 2017, 12:41   #1  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
Automatic white balance with RGBAdapt plugin

StainlessS, Fred,

I open this thread for my automatic white balance script based on the RGBAdapt plugin.

The various plugins necessary for its operation are indicated at the head of the script.
The script can use the AvsPmod user cursors. It is sufficient to uncomment lines 41 to 63.

The script can apply by color channel,
A correction of autogain, the force of this correction is adjustable from 0 to 100%,
A correction of gamma, the force of this correction is adjustable from 0 to 100%,
A bias correction, the force of this correction is adjustable from 0 to 100%,

The correction of gamma is a correction in accordance with the theory of the gray world. Indeed with this theory the bias correction is obtained by solving equation 128 = mean value - correction.
The gamma correction is thus obtained by solving the equation 128 = pow (mean value /255.0,1/correction gamma)

The script can also apply a contrast by channel. The value of this contrast is that of automatic gain after weighting. The application of this contrast is automatic according to a threshold relating to the difference between the greatest max value of the channels and the smallest min value.
This threshold is adjustable. With a value of zero it activates the contrast, with the value of 255 it deactivates the contrast.

Finally, the script adjusts the color temperature. This adjustment can be done automatically or manually.

The script also contains technical parameters, which if necessary need to be adjusted.
These allow you to fix the area of the image to be analyzed in order to extract the data (eliminates the influence of colored borders or a very large colored object in the center of the scene).
A threshold of not taking into account extreme pixels, adjustable from 0 to 100%. This threshold, set by default to 10%, only influences the result of the autogain.

I wanted to make a script giving an automatic white balance without adjustments, but the videos being almost all special cases, it often remains necessary to adjust the process.
To make the settings easier, the script can display a comparison of processes.
The two images at the top correspond to the default treatments without and with contrast.
The middle line shows the original, the result of coloryuv (autowhite), (this is to do better) and the output resulting from the operator settings.
The bottom line shows the result of other combinations, autogain alone, autogain and bias, autogain and gamma.

Finally, novelty of the version broadcast here, a new parameter.
In gray world theory, the average color of an image should be 128, in YUV space, it's good, but not in RGB space, because each channel carries a luma information.
By default, the script calculates the corrections of the gray world with respect to the average of the average values of each channel, calculated after the possible application of the gain. To the experience of some videos, it appeared to me that to allow to adjust from -50 to +50 this average of the average could be interesting.
Attached Files
File Type: txt RGBAdapt AWB Process.txt (51.5 KB, 143 views)

Last edited by Bernardd; 16th February 2018 at 17:34. Reason: delete dropbox link
Bernardd is offline   Reply With Quote
Old 12th March 2017, 10:22   #2  |  Link
martin53
Registered User
 
Join Date: Mar 2007
Posts: 404
Glad you're working on the topic. Maybe you want to read an earlier thread on AWB: Automatic White Balance (AWB) script function(s) (from your post, I don't think you are aware of it already, otherwise my apologies)
martin53 is offline   Reply With Quote
Old 12th March 2017, 12:08   #3  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
Hello martin53,
I know your thread. https://forum.doom9.org/showthread.p...15#post1672715
Happy news, since 2014 i have learned and now your script works fine on my old computer. But i do'nt know what was the problem in past.
My script target is to compensate color aberrations from aged film. Now my improve target is to find a good formula to fix gray value before to apply gamma and bias correction.
Thus i return to study your job.
Thanks.
Bernard
Bernardd is offline   Reply With Quote
Old 12th March 2017, 12:44   #4  |  Link
martin53
Registered User
 
Join Date: Mar 2007
Posts: 404
Back then I had the ideal to automatically detect the white balance bias (the correction step afterwards is not the main challenge, I felt).
Note that StainlessS was so kind to implement the Minkowski P-norm statistics function in his RT_Stats plugin especially for these purposes.

To my so far experiences back then, of the three common theories, White Patch best suited my taste for a wide range of footage (open sea, colorful nature scenery).
But it has a fundamental drawback when used on already recorded footage in contrast to internally in a recording device itself: all camera makes I studied create still fully white bright spots when used indoors with daylight setting.
In other words: everything is tinted in orange, but the bright spots are white, which cheats the White Patch approach.
(Besides of that, just to mention it: a useful AWB controller must have an alternative algorithm for footage where bright spots are completely absent.)
It turned out a dead end to limit the brightest pixels sent to White Patch to e.g. 20 luma increments below full white, because everyday footage can have already colorful objects in this luma range.

Then I followed the idea for a while, that objects (in terms of pixel examination: neighboured pixels with color inside a reasonable range) depict mainly the color of the light source in their comparably brighter areas, while in their comparably darker areas, they mainly depict the color of all surrounding reflections. This did not lead anyone to a formula for the light source color, however, because reflections color itself depends on the light source color...
Maybe the gray world theorem could be used for darker, reflection-dominated regions more than for the brighter regions. So i had to put my growing ever more complex studies aside for the moment.

Recently I was incited to put more thinking into the subject, when I read about homomorphic filtering, which was supposed to separate incident from reflected light, and second I wonder if it could be helpful to calculate the theoretical black body temperature for each pixel, and use the maximum, probably mainly of rather bright (but not fully white! see above) pixels to estimate the light source temperature. This is because I made the observation that blue objects under incandescent light, recorded with daylight white balance, are hopefully not so bright in typical footage that they would cheat this approach.

You are heartily welcome to find 'the' solution
martin53 is offline   Reply With Quote
Old 12th October 2017, 22:21   #5  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
Hello,
Here is a new version of the script.

The novelty is the possibility of restricting the extraction of RGB data by not taking into account
the pixels of the tones very dark and very bright. Thing is allowed with the use of a mask with function
RT_RgbChanStats from the powerful RT_Stats plugin.

This novelty combined with the use of contrast makes it possible to correct dominants of strong colors.

Today by default we find:

three display settings
comparison = compare different settings - (false or true)
show_scrutinized = shows the parsed area - (false or true)
show_info = displays extracted and calculated data - (false or true)

a technical adjustment
matrix = choice of the color conversion matrix (Rec 601 = 0 or Rec 709 = 1)

four settings to define the analyzed area
x = ignore pixels to the left - percentage of width - default: 0.00
Y = ignore pixels at the top - percentage of height - default: 0.00
w = ignores pixels to the right - percentage of width - default: 0.00
h = ignores pixels below - percentage of height - default: 0.00

a technical setting of RT_Stats
threshold = percentage of pixelx extreme to ignore - default: 0.10

twelve white balance automation settings
auto_tone_range = Enable tone selection of the pixels to be scanned - (false or true), true
tone_range = manual tone selection, ranges from 0 to 127, default 0
auto_luma_adjust = enable automatic adjustment of output luma - (false or true), default true
luma_adjust = manual adjustment of the luma adjustment - default: 0, varies from -50 to 50
auto_gain = automatic gain gain setting - (false or true), true default
gain_strength = manual gain control - default: 1.0, varies from 0.0 to 1.0
auto_cont = enable automatic contrast force setting - (false or true), true
cont_strength = manual adjustment of contrast strength - default: 1.0, varies from 0.0 to 1.0
auto_rpow = enable automatic rpow force setting - (false or true), default true
rpow_strength = manual rpow force setting - default: 1.0, varies from 0.0 to 1.0
auto_bias = enable automatic bias force setting - (false or true), true false
bias_strength = bias force manual setting - default: 1.0, varies from 0.0 to 1.0

two adjustment of color temperature adjustment
auto_temperature = enable automatic color temperature setting - (false or true) default false
temperature = manually setting the color temperature - default: 0.0, varies from -1.0 to 1.0

The number of these settings can be frightening. But in practice the default settings with all the automation activated
often give an acceptable result (in my opinion). When the result is not satisfactory, the output with the
comparisons makes it possible to identify the optimum adjustment combination.
In fine the setting for the color temperature is perhaps not useful today.
(Google Traduction)

The script in the three following posts

Last edited by Bernardd; 12th October 2017 at 22:30.
Bernardd is offline   Reply With Quote
Old 12th October 2017, 22:25   #6  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
Script part one
Quote:
######
### RGBAdapt_Awb_Process.avs, RGB32 + YV12 ONLY.
######

/*
AVISource("C:\.............\your video.avi")
LoadPlugin("C:\............\GRunT.dll")
LoadPlugin("C:\............\GScript.dll")
LoadPlugin("C:\............\RGBAdapt.dll")
LoadPlugin("C:\............\RT_Stats26.dll")
*/

# display tunings
comparison = false
show_scrutinized = True
show_info = True

# color space matrix tuning and specify the source rectangle under scrutiny
matrix = "Rec601"
x = 0.1
Y = 0.1
w = 0.1
h = 0.1

#extreme pixels percentage to be ignored when datas extraction
threshold = 0.1

# automatic white balance preset tunings
auto_tone_range = true
tone_range = 0
auto_luma_adjust = true
luma_adjust = 0
auto_gain = true
gain_strength = 1.0
auto_cont = true
cont_strength = 1.0
auto_rpow = true
rpow_strength = 1.0
auto_bias = true
bias_strength = 1.0
auto_temperature = false
temperature = 0.0

# If you use AvsPmod user sliders you can delete comment for following lines

#~ [<separator="display tunings">]
#~ comparison = Select([<"show different settings - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_scrutinized = Select([<"show scrutinized aera - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_info = Select([<"show datas - (false ou true) default = false = 0", 0, 1, 0>], false , true)

#~ [<separator="color space matrix tuning">]
#~ matrix = Select([<"color matrix - (Rec 601= 0 ou Rec 709 =1) = default = 0", 0, 1, 0>], "Rec601" , "Rec709")
#~ [<separator=""specify the source rectangle under scrutiny and percentage extreme pixels to ignore">]
#~ x = [<"ignore pixels on left - width percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ Y= [<"ignore pixels on top - heigth percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ w = [<"ignore pixels on right - width percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ h = [<"ignore pixels on bottom - heigth percentage - default : 0.00", 0.00, 0.99, 0.09>]
#~ [<separator=""specify the extreme pixels percentage to be ignored when datas extraction">]
#~ threshold = [<"percentage for extreme pixels to be ignored - default : 0.10", 0.00, 1.00, 0.1>]
#~ [<separator="automatic white balance tunings">]
#~ auto_tone_range = Select([<"automatic scrutinized channel tone area definition - (false ou true) default = true = 0", 0, 1, 1>], false , true)
#~ tone_range = [<"tone pixel range to analyze", 0, 127, 0>]
#~ auto_luma_adjust = Select([<"automatic output luma adjust - (false ou true) default = true = 0", 0, 1, 1>], false , true)
#~ luma_adjust = [<"output luma adjust - default : 0", -50, 50, 0>]
#~ auto_gain = Select([<"automatic gain strength - (false ou true) default = true = 0", 0, 1, 1>], false , true)
#~ gain_strength = [<"gain strength - default : 1.0", 0.0, 1.0, 0.0>]
#~ auto_cont = Select([<"automatic contrast strength - (false ou true) default = true = 0", 0, 1, 1>], false , true)
#~ cont_strength = [<"cont strength - default : 1.0", 0.0, 1.0, 0.0>]
#~ auto_rpow = Select([<"automatic rpow strength - (false ou true) default = true = 0", 0, 1, 1>], false , true)
#~ rpow_strength = [<"rpow strength - default : 1.0", 0.0, 1.0, 0.0>]
#~ auto_bias = Select([<"automatic bias strength - (false ou true) default = true = 0", 0, 1, 1>], false , true)
#~ bias_strength = [<"final bias strength - default : 1.0", 0.0, 1.0, 0.0>]
#~ [<separator="color temperature tunings">]
#~ auto_temperature = Select([<"automatic color temperature - (false ou true) default = true = 1", 0, 1, 0>], false , true)
#~ temperature = [<"manual color temperature - default : 0.0", -1.0, 1.0, 0.0>]


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

/*
# Without Stacked View capability
a = RGBAdapt_AWB_Process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h,
\ threshold=threshold,threshold_auto=threshold_auto,
\ gain_strength=gain_strength, luma_adjust = luma_adjust,r pow_strength=rpow_strength, bias_strength=bias_strength,
\ auto_temperature = auto_temperature, temperature = temperature)
*/

# With Stacked View capability

AWB_Func(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h,
\ threshold=threshold, auto_tone_range = auto_tone_range, tone_range= tone_range, auto_luma_adjust= auto_luma_adjust, luma_adjust = luma_adjust,
\ auto_gain = auto_gain, auto_cont = auto_cont, auto_rpow = auto_rpow, auto_bias = auto_bias,
\ gain_strength=gain_strength, cont_strength=cont_strength, rpow_strength=rpow_strength, bias_strength=bias_strength,
\ auto_temperature = auto_temperature, temperature = temperature,
\ Comparison=Comparison)

Return Last

/*
#----------------------------------------------based on RGBADapt plugin --------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=170642 #
#-------------------------------------------------------------------------------------------------------------------#

#---------------------------------------------- need RT_Stats plugin -----------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=165479 #
#-------------------------------------------------------------------------------------------------------------------#

#---------------------------------------------- need GRunT plugin --------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=139337 #
#-------------------------------------------------------------------------------------------------------------------#

#---------------------------------------------- need GScript plugin ------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=147846 #
#-------------------------------------------------------------------------------------------------------------------#
*/

Function RGBAdapt_AWB_Process(clip clip,string "matrix",bool "show_scrutinized",bool "show_info",float "x",float "y",float "w",float "h",
\ float "threshold", bool "auto_tone_range", int "tone_range", bool "auto_luma_adjust", int "luma_adjust",
\ bool "auto_gain", bool "auto_cont", bool "auto_rpow", bool "auto_bias",
\ float "gain_strength", float "cont_strength", float "rpow_strength", float "bias_strength",
\ bool "auto_temperature", float "temperature") {

# Clip MUST be YV12 or RGB32. Always returns SAME colorspace as input.
clip
myName="RGBAdapt_Awb_Process: "
Assert(RT_FunctionExist("RGBAdapt"),myName+"RGBAdapt plugin must be loaded, http://forum.doom9.org/showthread.php?t=170642")
Assert(RT_FunctionExist("GScriptClip"),myName+"GRunT plugin must be loaded, http://forum.doom9.org/showthread.php?t=139337")
Assert(RT_FunctionExist("GScript"),myName+"GScript plugin must be loaded, http://forum.doom9.org/showthread.php?t=147846")
Assert(IsYV12(clip) || IsRGB32(clip),RT_String("%sInput video colorspace must be YV12 or RGB32",myName))
matrix = Default(matrix, "Rec601") # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709",RT_String("%smatrix 'Rec601' or 'Rec709'('%s')",myName,matrix))
show_scrutinized = Default(show_scrutinized, false) # show scrutinized area or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.0)) # width percentage to specify coords source rectangle under scrutiny, the default : x=y=h=w=0.0 full frame
Assert(0.0 <= x <= 0.99,RT_String("%s0.0 <= x <= 0.99(%f)",myName,x))
y = float(Default(y,0.0)) # height percentage to specify coords source rectangle under scrutiny, the default : x=y=h=w=0.0 full frame
Assert(0.0 <= y <= 0.99,RT_String("%s0.0 <= y <= 0.99(%f)",myName,y))
w = float(Default(w,0.0)) # coords specify source rectangle under scrutiny, the default : x=y=h=w=0.0 is full frame
Assert(0.0 <= w <= 0.99,RT_String("%s0.0 <= w <= 0.99(%f)",myName,w))
Assert(0.0 <= (x+w) <= 0.99 ,RT_String("%s0.0 <= (x+w) <= 0.99(%f)",myName,x+w))
h = float(Default(h,0.0)) # coords specify source rectangle under scrutiny , the default : x=y=h=w=0.0 is full frame
Assert(0.0 <= h <= 0.99,RT_String("%s0.0 <= h <= 0.99(%f)",myName,h))
Assert(0.0 <= (y+h) <= 0.99 ,RT_String("%s0.0 <= (y+h) <= 0.99(%f)",myName,y+h))
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(0.0 <= threshold <= 1.0,RT_String("%s0.0 <= threshold <= 1.0(%f)",myName,threshold))
auto_tone_range = Default(auto_tone_range, true) # enable automatic scrutinized channel tone area definition, default true
tone_range = Int(Default(tone_range, 0)) #luma range to select tone pixel to analyze
Assert(0 <= tone_range <= 127,RT_String("%s0 <= tone_range <= 127(%f)",myName,tone_range))
auto_luma_adjust = Default(auto_luma_adjust, true) # enable automatic output luma adjust, default true
luma_adjust = Int(Default(luma_adjust, 0)) # automatic output luma adjust
Assert(-50 <= luma_adjust <= 50,RT_String("%s-50 <= luma_adjust <= 50(%f)",myName,luma_adjust))
auto_gain = Default(auto_gain, true) # enable automatic cont strength, default true
gain_strength = Float(Default(gain_strength, 1.0)) # gain strength
Assert(0.0 <= gain_strength <= 1.0,RT_String("%s0.0 <= gain_strength <= 1.0(%f)",myName,gain_strength))
auto_cont = Default(auto_cont, true) # enable automatic cont strength, default true
cont_strength = Float(Default(cont_strength, 1.0)) # cont strength
Assert(0.0 <= cont_strength <= 1.0,RT_String("%s0.0 <= cont_strength <= 1.0(%f)",myName,cont_strength))
auto_rpow = Default(auto_rpow, true) # enable automatic cont strength, default true
rpow_strength = Float(Default(rpow_strength, 1.0)) #rpow strength
Assert(0.0 <= rpow_strength <= 1.0,RT_String("%s0.0 <= rpow_strength <= 1.0(%f)",myName,rpow_strength))
auto_bias = Default(auto_bias, true) # enable automatic cont strength, default true
bias_strength = Float(Default(bias_strength, 1.0)) #bias strength
Assert(0.0 <= bias_strength <= 1.0,RT_String("%s0.0 <= bias_strength <= 1.0(%f)",myName,bias_strength))
auto_temperature = Default(auto_temperature, true) # enable automatic color temperature factor, default true
temperature = Float(Default(temperature, 0.0)) # manual color temperature factor
Assert(- 1.0 <= temperature <= 1.0,RT_String("%s-1.0 <= temperature <= 1.0(%f)",myName,temperature))

#---------- Specify the source rectangle under scrutiny, x,y,w,h are now type Int

x = int( Width * x)
y = int( Height * y)
w = int(-Width * w)
h = int(-Height * h)

#--------- RGB color space process

RGB32_clip = (!isRGB32(clip)) ? ConvertToRGB32(clip, matrix=matrix) : clip

CWID=72 CHIT=24 #69 21 # display Width and Height in Subtitle characters
MinWid=CWID*10 MinHit=CHIT*20 # RT_Subtitle required width height in pixels (fixed font size is 10x20)
TooSmall=(Width<MinWid || Height<MinHit)

RedStr = (TooSmall) ? "Red values :\n" : "\a2Red values\a- :\n"
GrnStr = (TooSmall) ? "Green values :\n" : "\a4Green values\a- :\n"
BluStr = (TooSmall) ? "Blue values :\n" : "\a1Blue values\a- :\n"

# Use same string at each frame.
Fmt=
\ "\nORI Channels averages average : %7.3f Auto strength :%7.3f" +
\ "\nChannels averages average : %7.3f\n" +
\ "Min max ave diff (for auto contrast tune) : %7.3f\n" +
\ RedStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " R_bias=%7.3f : R_gain =%7.3f : R_cont =%.3f : R_rpow=%.3f\n\n" +
\ GrnStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " G_bias=%7.3f : G_gain =%7.3f : G_cont =%.3f : G_rpow=%.3f\n\n" +
\ BluStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " B_bias=%7.3f : B_gain =%7.3f : B_cont =%.3f : B_rpow=%.3f\n\n" +
\ "Channels averages average : %7.3f \n\nColor temperature mod = %.1f percent of %s (max 6.0 percent)"
Bernardd is offline   Reply With Quote
Old 12th October 2017, 22:28   #7  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
Script part two
Quote:

GSCript("""
# Nested Low level Function, Called per frame via GScriptClip(), RGB32 ONLY
Function RGBAdapt_awb_process_Lo(clip clp,String Fmt,bool show_info,int x,int y,int w,int h,float threshold,
\ bool auto_tone_range, int tone_range, bool auto_luma_adjust, int luma_adjust,
\ bool auto_gain, bool auto_cont, bool auto_rpow, bool auto_bias,
\ float gain_strength,float cont_strength, float rpow_strength, float bias_strength,
\ Bool TooSmall,Int CWid,Int CHit,bool auto_temperature, float temperature) {

clp # Last = Input RGB32 clp clip.

# n = current_frame # n is current_frame, can use in RT_Stats to access frames relative to current. Not currently Used.

#---------- Channels datas extraction and adjustement factors calculation

Last.RT_RgbChanStats(x=x,y=y,w=w,h=h,threshold=threshold,chan=-1,flgs= 1+2+4+16, Prefix="RCS_")

blank_clip = RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2 # one color clip detection to disable auto white balance

ORI_Ave_0 = RCS_Ave_0 ORI_Ave_1 = RCS_Ave_1 ORI_Ave_2 = RCS_Ave_2

auto_strength = Min((ORI_Ave_0 + ORI_Ave_1 + ORI_Ave_2)/(3.0*128.0),1.0) # automatic strength for all process

if (auto_tone_range) {ref_ori = (ORI_AVE_0+ORI_AVE_1+ORI_AVE_2)/3.0
tone_range = max(round((128.0 - ref_ori)/3.0),0)} # automatic pixel luma range to analyze

Last.RT_RgbChanStats(x=x,y=y,w=w,h=h,threshold=threshold,chan=0,flgs= 1+2+4+16,mask=last.ShowRed("YV12"),MaskMin=tone_range,MaskMax=255 - tone_range)
Last.RT_RgbChanStats(x=x,y=y,w=w,h=h,threshold=threshold,chan=1,flgs= 1+2+4+16,mask=last.ShowGreen("YV12"),MaskMin=tone_range,MaskMax=255 - tone_range)
Last.RT_RgbChanStats(x=x,y=y,w=w,h=h,threshold=threshold,chan=2,flgs= 1+2+4+16,mask=last.ShowBlue("YV12"),MaskMin=tone_range,MaskMax=255 - tone_range)

if (auto_luma_adjust) {luma_adjust = tone_range} # automatic output luma adjust to avoid darkness given by contrast

# Leave RCS_ values as original (avoid repeat function call in Show_info), new variables without RCS_ prefix, avoid div by zero.
MinMaxDiff_0 = Max(RCS_MinMaxDiff_0, 0.00001)
MinMaxDiff_1 = Max(RCS_MinMaxDiff_1, 0.00001)
MinMaxDiff_2 = Max(RCS_MinMaxDiff_2, 0.00001)

#---------- Gain process

if (auto_gain) {gain_strength = auto_strength}

r_gain = 1.0 + (255.0/MinMaxDiff_0 - 1.0) * gain_strength
r_gain_bias = -RCS_Min_0 * r_gain *gain_strength
g_gain = 1.0 + (255.0/MinMaxDiff_1 - 1.0) * gain_strength
g_gain_bias = -RCS_Min_1 * g_gain * gain_strength
b_gain = 1.0 + (255.0/MinMaxDiff_2 - 1.0) * gain_strength
b_gain_bias = -RCS_Min_2 * b_gain * gain_strength

#------ Contrast process

# Cont is dangerous, because it can overshoot light and dark, but it is necessary to help to find good correction for very big
# color cast.

#~ if (auto_cont) {cont_strength = auto_strength}
if (auto_cont) {cont_strength = (ORI_Ave_0 + ORI_Ave_1 + ORI_Ave_2)/(3.0*128.0)
if (cont_strength > 1.0) {cont_strength = cont_strength - 1.0} else {cont_strength = cont_strength}}

r_cont = 1.0 + (r_gain - 1.0) * cont_strength
r_cont_max = RCS_Max_0 * r_gain + r_gain_bias + (r_cont - 1) * (RCS_Max_0 - 128)
r_cont_bias = (255 - r_cont_max) * gain_strength

g_cont = 1.0 + (g_gain - 1.0) * cont_strength
g_cont_max = RCS_Max_1 * g_gain + g_gain_bias + (g_cont - 1) * (RCS_Max_1 - 128)
g_cont_bias = (255 - g_cont_max) * gain_strength

b_cont = 1.0 + (b_gain - 1.0) * cont_strength
b_cont_max = RCS_Max_2 * b_gain + b_gain_bias + (b_cont - 1) * (RCS_Max_2 - 128)
b_cont_bias = (255 - b_cont_max) * gain_strength

r_bias = r_gain_bias +r_cont_bias g_bias = g_gain_bias +g_cont_bias b_bias = b_gain_bias + b_cont_bias

#----gamma args calculation in accordance with gray world theory

# In gray world theory, in YUV range, we increase or decrease average value to ref = 128.0, but in RGB range
# ref = average of channel average values is better.
# With contrast use, average of channel average value after gain process without cont process give a better picture light.

# In gamma process, to incresae or decrease average value, we use gamma args. To find this gamma args, we
# solve this equation ref = pow(average value/255.0,1/gamma args)

ref = (RCS_Ave_0 * r_gain + r_gain_bias + RCS_Ave_1 * g_gain + g_gain_bias + RCS_Ave_2 * b_gain + b_gain_bias)/3.0 + luma_adjust

# Warm temperature = gray mixed with 6% yellow. Cool temperature = gray mixed with 6% blue. (https://en.wikipedia.org/wiki/Color_temperature)
# thus with temperature factor, you can adjust color temperature in manual or automatic mode.

if (auto_temperature) {
temperature = (ref - Min(RCS_Ave_0, RCS_Ave_2))/ref} # else temperature = manual temperature args
#~ add_color = (temperature >= 0) ? "yellow" : "blue" # this variable is only for display

if (auto_rpow) {rpow_strength = auto_strength}

r_rpow = 1 + (log((RCS_Ave_0 * r_gain + r_gain_bias)/255.0)/log(ref * (1 + 0.06 * temperature)/255.0) - 1) * rpow_strength
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 + (log((RCS_Ave_1 * g_gain + g_gain_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 + (log((RCS_Ave_2 * b_gain + b_gain_bias)/255.0)/log(ref * (1 - 0.06 * temperature)/255.0) - 1) * rpow_strength
b_rpow = Min (4.0, Max (b_rpow, 0.1))

#--------- bias gain cont in RGBadapt args range

r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))
r_gain = Min (8.0, Max (r_gain, -8.0)) g_gain = Min (8.0, Max (g_gain, -8.0)) b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0)) g_cont = Min (8.0, Max (g_cont, -8.0)) b_cont = Min (8.0, Max (b_cont, -8.0))

#---------- bias corrections in accordance with gray world theory
#----------- bias corrections extraction and calcul
# ssS, Create and measure temp clip

TempC=clp.RGBAdapt(R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow,
\ G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow,
\ B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow)

TempC.RT_RgbChanStats(x=x,y=y,w=w,h=h,threshold=threshold,chan=-1,flgs=16,Prefix="TMP_") ### Use TMP_ prefix HERE

# Ref for bias corrections always calculated with gain output, because is more light than calculated with new extracted channels average values

if (auto_bias) {bias_strength = auto_strength}

dr = (ref * (1 + 0.06 * temperature) - TMP_Ave_0) * bias_strength dg = (ref - TMP_Ave_1) * bias_strength
db = (ref * (1 - 0.06 * temperature) - TMP_Ave_2) * bias_strength

r_bias = (r_gain_bias + r_cont_bias + dr) g_bias = (g_gain_bias + g_cont_bias + dg) b_bias = (b_gain_bias + b_cont_bias + db)
r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))

#------------ AWB output with gain cont rpow and bias process
# now change for real

(blank_clip==0)
\ ? clp
\ : clp.RGBAdapt(R_bias=r_bias,R_Gain=r_gain,R_Cont=r_cont,R_rpow=r_rpow,
\ G_bias=g_bias,G_Gain=g_gain,G_Cont=g_cont,G_rpow=g_rpow,
\ B_bias=b_bias,B_Gain=b_gain,B_Cont=b_cont,B_rpow=b_rpow)

if(show_info) {
#--------- final RGB values extraction for display
# Use different 'FIN_' Prefix so as not to destroy original variables

add_color = (temperature >= 0) ? "yellow" : "blue" # this variable is only for display

Last.RT_RgbChanStats(x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16,Prefix="FIN_")

S=RT_String(Fmt,
\ (ORI_Ave_0+ORI_Ave_1+ORI_Ave_2)/3.0,auto_strength,
\ (RCS_Ave_0+RCS_Ave_1+RCS_Ave_2)/3.0, Max(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2) - Min(RCS_Ave_0,RCS_Ave_1,RCS_Ave_2),
\
\ RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0,
\ FIN_Ave_0, FIN_MinMaxDiff_0, FIN_Min_0, FIN_Max_0,
\ r_bias, r_gain,r_cont,r_rpow,
\
\ RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1,
\ FIN_Ave_1, FIN_MinMaxDiff_1, FIN_Min_1, FIN_Max_1,
\ g_bias, g_gain,g_cont,g_rpow,
\
\ RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2,
\ FIN_Ave_2, FIN_MinMaxDiff_2, FIN_Min_2, FIN_Max_2,
\ b_bias,b_gain,b_cont,b_rpow,
\
\ (FIN_Ave_0 + FIN_Ave_1 + FIN_Ave_2 )/3, temperature*0.06*100,add_color, Esc=(TooSmall)?0:1)

(TooSmall)
\ ? Last.Subtitle(S,Font="Courier New",lsp=0,text_color=$FFFF00,halo_color=$0,size=height/float(CHIT),
\ Font_width=width/FloaT(CWID))
\ : Last.RT_Subtitle("%s",S)
} # End ShowInfo
Return Last
} # End, RGBAdapt_awb_process_Lo()

# GScriptClip, Calling Low level Function RGBAdapt_awb_process_Lo() at each frame.
# Named ARGS variables at current script level, are imported into GScriptClip script, and passed as args to RGBAdapt_awb_process_Lo().
ARGS="Fmt,show_info,x,y,w,h,threshold, auto_tone_range, tone_range, auto_luma_adjust, luma_adjust," +
" auto_gain, auto_cont, auto_rpow, auto_bias, gain_strength, cont_strength, rpow_strength, bias_strength, TooSmall,CWid,CHit," +
"auto_temperature, temperature"
RGB32_clip.GScriptClip("RGBAdapt_awb_process_Lo(last,"+ARGS+")", local=true, args=ARGS)

# Do border outside of Scriptclip.
if(show_scrutinized) {
Level = 100 # 0 (Off) -> 257 (Full)
MarkColor = $00FF00
#-------- display scrutinized area
scrutinized_green = Last.BlankClip(width = Width-x+w, height = height-y+h, color=MarkColor)
scrutinized_mask = scrutinized_green.Blankclip(color=$0).LetterBox(2,2,2,2,$FFFFFF)
Layer(last,scrutinized_green.Mask(scrutinized_mask),x=x,y=y,level=Level)
} # End show_scrutinized
""")
Return (clip.isYV12) ? ConvertToYV12(last, matrix=matrix) : last # Return original colorspace, YV12 or RGB32
}
Bernardd is offline   Reply With Quote
Old 12th October 2017, 22:29   #8  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
Script part three
Quote:

Function AWB_Func(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h",
\ float "threshold", bool "auto_tone_range", int "tone_range", bool "auto_luma_adjust", int "luma_adjust",
\ bool "auto_gain", bool "auto_cont", bool "auto_rpow", bool "auto_bias",
\ float "gain_strength",float "cont_strength", float "rpow_strength", float "bias_strength",
\ bool "auto_temperature", float "temperature", bool "Comparison") {

# Clip MUST be YV12 or RGB32. Always returns SAME colorspace as input.
Gscript("""
clip
output=clip.RGBAdapt_Awb_Process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,x=x,y=y,w=w,h=h,threshold=threshold,
\ auto_tone_range = auto_tone_range, tone_range = tone_range, auto_luma_adjust = auto_luma_adjust, luma_adjust=luma_adjust,
\ auto_gain = auto_gain, auto_cont = auto_cont, auto_rpow = auto_rpow, auto_bias = auto_bias,
\ gain_strength=gain_strength, cont_strength=cont_strength, rpow_strength=rpow_strength, bias_strength=bias_strength,
\ auto_temperature = auto_temperature, temperature = temperature)
if (!Default(Comparison,false)) {
output
} else {
# Here, Clip is either RGB32 or YV12.
# Ensure RGB32 for all calls to RGBAdapt_Awb_Process (Only convert input at most once)
RGB_Clip = (Clip.IsYV12) ? clip.ConvertToRGB32(matrix=matrix) : clip
full = RGB_Clip.RGBAdapt_awb_process(matrix=matrix, show_scrutinized=show_scrutinized, show_info=show_info,
\ x=x, y=y, w=w, h=h,auto_gain = false, auto_tone_range = false, tone_range = 0,auto_temperature = false, temperature = 0.0)
without_contrast = RGB_Clip.RGBAdapt_awb_process(matrix=matrix, show_scrutinized=show_scrutinized, show_info=show_info,
\ x=x, y=y, w=w, h=h,auto_cont = false, cont_strength =0.0,auto_temperature = false, temperature = 0.0)
without_rpow = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized, show_info=show_info,
\ x=x,y=y,w=w,h=h,auto_rpow = false, rpow_strength =0.0,auto_temperature = false,temperature = 0.0)
without_bias = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h, auto_bias= false, bias_strength =0.0,auto_temperature = false,temperature = 0.0)
without_gain = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h, auto_gain = false, gain_strength =0.0, temperature = temperature)
only_gain = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h, threshold=0.1,auto_cont = false,cont_strength =0.0,auto_rpow = false, rpow_strength=0.0,
\auto_bias = false, bias_strength=0.0,temperature = temperature)

YV12_Clip = (clip.IsRGB32) ? clip.ConvertToYV12(matrix=matrix) : clip
colorYUV_AWB = YV12_Clip.ColorYUV(autowhite = true)

# Convert clips to original Input ColorSpace.
if(clip.IsRGB32) {
colorYUV_AWB = colorYUV_AWB.ConvertToRGB32(matrix=matrix)
} else {
full = full.ConvertToYV12(matrix=matrix)
without_contrast = without_contrast.ConvertToYV12(matrix=matrix)
without_rpow = without_rpow.ConvertToYV12(matrix=matrix)
without_bias = without_bias.ConvertToYV12(matrix=matrix)
without_gain = without_gain.ConvertToYV12(matrix=matrix)
only_gain = only_gain.ConvertToYV12(matrix=matrix)
}

#~ contrast_label=(cont_strength==0.0) ? "without contrast"
#~ \ : (cont_strength>0.0) ? "with contrast"
#~ \ : "contrast in accordance with threshold"

STK1 = StackHorizontal(
\ without_rpow.AddBorders(0,20,0,0,color=$0).Subtitle("gain contrast and bias process without rpow"),
\ without_bias.AddBorders(0,20,0,0,color=$0).Subtitle("gain contrast and rpow process without bias"),
\ full.AddBorders(0,20,0,0,color=$0).Subtitle("default without color analyzerestriction")
\ )
STK2 = StackHorizontal(
\ clip.AddBorders(0,20,0,0,color=$0).Subtitle("original"),
\ colorYUV_AWB.AddBorders(0,20,0,0,color=$0).Subtitle("As a reminder, classical ColorYUV awb"),
\ output.AddBorders(0,20,0,0,color=$0).Subtitle ("Selected output")
\ )
STK3 = StackHorizontal(
\ only_gain.AddBorders(0,20,0,0,color=$0).Subtitle("only gain "),
\ without_gain.AddBorders(0,20,0,0,color=$0).Subtitle("only rpow and bias without contrast"),
\ without_contrast.AddBorders(0,20,0,0,color=$0).Subtitle("gain rpow and bias process without contrast")
\ )
StackVertical(STK1,STK2,STK3)
} # End, if
""") # End GScript
Return Last # Return Original ColorSpace
}
Bernardd is offline   Reply With Quote
Old 20th November 2017, 03:12   #9  |  Link
Sachin
Registered User
 
Join Date: Nov 2017
Location: India
Posts: 11
Bernard,
Thank you for this wonderful script, the script posted in first post works simply superb. I wanted to try the new version in the above three posts, it gives me following error

Script error: syntax error
([GScript], line 169, column 0)
(C:\Desktop\RGBAdapt_Awb_Process.avs, line 392)
([GScript], line 7)
(C:\Desktop\RGBAdapt_Awb_Process.avs, line 467)
(C:\Desktop\RGBAdapt_Awb_Process.avs, line 99)

I believe that this is a copy/paste error. It will be very helpful if you can post the whole new version script in a single part avs file so that I can download.

Thank you

Last edited by Sachin; 20th November 2017 at 03:14. Reason: To make more specific
Sachin is offline   Reply With Quote
Old 20th November 2017, 05:02   #10  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 8,422
Same here, but slight difference in line numbers (due to blank lines probably)

Code:
([GScript], line 169, column 0)
(C:\Desktop\RGBAdapt_Awb_Process.avs, line 395)
([GScript], line 7)
(C:\Desktop\RGBAdapt_Awb_Process.avs, line 469)
(C:\Desktop\RGBAdapt_Awb_Process.avs, line 102)
I'm not gonna attempt to find fix, cannot stand unformatted script, and Bernard keeps removing all formatting despite [EDIT: near] zero speed increase benefit.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 20th November 2017 at 10:07.
StainlessS is offline   Reply With Quote
Old 20th November 2017, 17:42   #11  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
Hello,
Sachin, StainlessS, i apology.

The error lines are these
ARGS="Fmt,show_info,x,y,w,h,threshold, auto_tone_range, tone_range, auto_luma_adjust, luma_adjust," +
" auto_gain, auto_cont, auto_rpow, auto_bias, gain_strength, cont_strength, rpow_strength, bias_strength, TooSmall,CWid,CHit," +
"auto_temperature, temperature"
They should be this :
ARGS="Fmt,show_info,x,y,w,h,threshold, auto_tone_range, tone_range, auto_luma_adjust, luma_adjust," +
\ " auto_gain, auto_cont, auto_rpow, auto_bias, gain_strength, cont_strength, rpow_strength, bias_strength," +
\ " TooSmall,CWid,CHit,auto_temperature, temperature"

But i suggest to do'nt spend much time to try the last script version, because i propose a new version.

New script more short, more useable.

More short, definitively only four ways for color cast correction.
action with gain,
action with contrast (new formula without color channel ponderation factors),
action with rpow,
action with bias.
This four actions can work together or independantly. Each action have thus a tunable power strength .

If you want, each action power strength can be equal and give a readable white balance. Thus it is more useable,
you have only one common strength to tune. More useable the script have a automatic mode to compute this
common strength. His white balance result is often readable. More useable it is fast to disable the common strength
for one, two or three actions to fine the white balance. At this time, you can also tune the power strength of the
actions of your choice to refine the white balance.

The script have a comparison display mode to help to find the better combination of the four actions.
This mode show nine output of the video.
Top, without contrast action, in automatic common strength mode, you have from rigth to left gain action only,
gain and bias actions, and gain, rpow and bias actions.
Middle, from rigth to left, original input, AutoWhite ColorYUV process, and the tuned script output.
Bottom, from rigth to left, with automatic common strength desable, but with common strength eaqual to 1.0
gain and contrast actions, gain, contrast, and bias actions and gain, contrast, rpow and bias actions.

Comment
The automatic common strength factor is an aproximation. Color cast is problem with color channel average and or
min and max values. Thus common_strength = (channel average average + channel min average + channel
max average))/(128+255). This formula gives often good results with low color cast, but for heavy color cast
the strength of the four actions is to few. In this case you must disable automatic common strength and tune it in
manual mode. You can also experiment the own manual tune of each actions.

and in following posts.

Bernard

Last edited by Bernardd; 16th February 2018 at 17:33. Reason: delete dropbox link
Bernardd is offline   Reply With Quote
Old 20th November 2017, 17:51   #12  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
script first part
Quote:
######
### RGBAdapt_Awb_Process.avs, RGB32 + YV12 ONLY.
######

/*
AVISource("C:\.............\your video.avi")
LoadPlugin("C:\............\GRunT.dll")
LoadPlugin("C:\............\GScript.dll")
LoadPlugin("C:\............\RGBAdapt.dll")
LoadPlugin("C:\............\RT_Stats26.dll")
*/

# display tunings
comparison = false
show_scrutinized = true
show_info = true

# color space matrix tuning and specify the source rectangle under scrutiny
matrix = "Rec601"
x = 0.1
Y = 0.1
w = 0.1
h = 0.1

#extreme pixels percentage to be ignored when datas extraction
threshold = 0.1

# automatic white balance preset tunings
auto_strength = true
common_strength = 1.0
common_gain = true
gain_strength = 0.0
common_cont = true
cont_strength = 0.0
common_rpow = true
rpow_strength = 0.0
common_bias = true
bias_strength = 0.0

# If you use AvsPmod user sliders you can delete comment for following lines

#~ [<separator="display tunings">]
#~ comparison = Select([<"show different settings - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_scrutinized = Select([<"show scrutinized aera - (false ou true) default = false = 0", 0, 1, 0>], false , true)
#~ show_info = Select([<"show datas - (false ou true) default = false = 0", 0, 1, 0>], false , true)

#~ [<separator="color space matrix tuning">]
#~ matrix = Select([<"color matrix - (Rec 601= 0 ou Rec 709 =1) = default = 0", 0, 1, 0>], "Rec601" , "Rec709")
#~ [<separator=""specify the source rectangle under scrutiny and percentage extreme pixels to ignore">]
#~ x = [<"ignore pixels on left - width percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ Y= [<"ignore pixels on top - heigth percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ w = [<"ignore pixels on right - width percentage - default : 0.00", 0.00, 0.99, 0.11>]
#~ h = [<"ignore pixels on bottom - heigth percentage - default : 0.00", 0.00, 0.99, 0.1>]
#~ [<separator=""specify the extreme pixels percentage to be ignored when datas extraction">]
#~ threshold = [<"percentage for extreme pixels to be ignored - default : 0.10", 0.00, 1.00, 0.1>]
#~ [<separator="automatic white balance tunings - global process tune">]
#~ auto_strength = Select([<"automatic strength process - (false ou true) default = true = 0", 0, 1, 1>], false , true)
#~ common_strength = [<"---- manual common strength - default : 1.00", 0.00, 2.00, 1.0>]
#~ [<separator="automatic white balance tunings - individual process tune">]
#~ common_gain = Select([<"common gain strength - (false ou true) default = true = 0", 0, 1, 1>], false , true)
#~ gain_strength = [<"---- manual gain strength - default : 0.0", 0.0, 2.0, 0.0>]
#~ common_cont = Select([<"common contrast strength - (false ou true) default = true = 0", 0, 1, 1>], false , true)
#~ cont_strength = [<"---- manual cont strength - default : 0.0", 0.0, 2.0, 0.0>]
#~ common_rpow = Select([<"common rpow strength - (false ou true) default = true = 0", 0, 1, 1>], false , true)
#~ rpow_strength = [<"---- manual rpow strength - default : 0.0", 0.0, 2.0, 0.0>]
#~ common_bias = Select([<"common bias strength - (false ou true) default = true = 0", 0, 1, 1>], false , true)
#~ bias_strength = [<"---- manual bias strength - default : 0.0", 0.0, 2.0, 0.0>]

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

/*
# Without Stacked View capability
a = RGBAdapt_AWB_Process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h,
\ threshold=threshold,threshold_auto=threshold_auto,
\ gain_strength=gain_strength, luma_adjust = luma_adjust,r pow_strength=rpow_strength, bias_strength=bias_strength)
*/

# With Stacked View capability

AWB_Func(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h,
\ threshold=threshold, auto_strength = auto_strength, common_strength = common_strength,
\ common_gain = common_gain, common_cont = common_cont, common_rpow = common_rpow, common_bias = common_bias,
\ gain_strength=gain_strength, cont_strength=cont_strength, rpow_strength=rpow_strength, bias_strength=bias_strength,
\ Comparison=Comparison)

/*
#----------------------------------------------based on RGBADapt plugin --------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=170642 #
#-------------------------------------------------------------------------------------------------------------------#

#---------------------------------------------- need RT_Stats plugin -----------------------------------------------#
# script author : StainlessS http://forum.doom9.org/showthread.php?t=165479 #
#-------------------------------------------------------------------------------------------------------------------#

#---------------------------------------------- need GRunT plugin --------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=139337 #
#-------------------------------------------------------------------------------------------------------------------#

#---------------------------------------------- need GScript plugin ------------------------------------------------#
# plugin author : Gavino http://forum.doom9.org/showthread.php?t=147846 #
#-------------------------------------------------------------------------------------------------------------------#
*/

Function RGBAdapt_AWB_Process(clip clip,string "matrix",bool "show_scrutinized",bool "show_info",float "x",float "y",float "w",float "h",
\ float "threshold", bool "auto_strength", float "common_strength",
\ bool "common_gain", bool "common_cont", bool "common_rpow", bool "common_bias",
\ float "gain_strength", float "cont_strength", float "rpow_strength", float "bias_strength") {

# Clip MUST be YV12 or RGB32. Always returns SAME colorspace as input.
clip
myName="RGBAdapt_Awb_Process: "
Assert(RT_FunctionExist("RGBAdapt"),myName+"RGBAdapt plugin must be loaded, http://forum.doom9.org/showthread.php?t=170642")
Assert(RT_FunctionExist("GScriptClip"),myName+"GRunT plugin must be loaded, http://forum.doom9.org/showthread.php?t=139337")
Assert(RT_FunctionExist("GScript"),myName+"GScript plugin must be loaded, http://forum.doom9.org/showthread.php?t=147846")
Assert(IsYV12(clip) || IsRGB32(clip),RT_String("%sInput video colorspace must be YV12 or RGB32",myName))
matrix = Default(matrix, "Rec601") # Color standard, Rec 601 or Rec 709
Assert(matrix == "Rec601" || matrix == "Rec709",RT_String("%smatrix 'Rec601' or 'Rec709'('%s')",myName,matrix))
show_scrutinized = Default(show_scrutinized, false) # show scrutinized area or not, default false
show_info = Default(show_info, false) # show info or not, default false
x = float(Default(x,0.0)) # width percentage to specify coords source rectangle under scrutiny, the default : x=y=h=w=0.0 full frame
Assert(0.0 <= x <= 0.99,RT_String("%s0.0 <= x <= 0.99(%f)",myName,x))
y = float(Default(y,0.0)) # height percentage to specify coords source rectangle under scrutiny, the default : x=y=h=w=0.0 full frame
Assert(0.0 <= y <= 0.99,RT_String("%s0.0 <= y <= 0.99(%f)",myName,y))
w = float(Default(w,0.0)) # coords specify source rectangle under scrutiny, the default : x=y=h=w=0.0 is full frame
Assert(0.0 <= w <= 0.99,RT_String("%s0.0 <= w <= 0.99(%f)",myName,w))
Assert(0.0 <= (x+w) <= 0.99 ,RT_String("%s0.0 <= (x+w) <= 0.99(%f)",myName,x+w))
h = float(Default(h,0.0)) # coords specify source rectangle under scrutiny , the default : x=y=h=w=0.0 is full frame
Assert(0.0 <= h <= 0.99,RT_String("%s0.0 <= h <= 0.99(%f)",myName,h))
Assert(0.0 <= (y+h) <= 0.99 ,RT_String("%s0.0 <= (y+h) <= 0.99(%f)",myName,y+h))
threshold = Float(Default(threshold, 0.10)) # threshold arg of RT_Stats plugin
Assert(0.0 <= threshold <= 1.0,RT_String("%s0.0 <= threshold <= 1.0(%f)",myName,threshold))
auto_strength = Default(auto_strength, true) # enable automatic cont strength, default true
common_strength = Float(Default(common_strength, 1.0)) # common strength
Assert(0.0 <= common_strength <= 2.0,RT_String("%s0.0 <= common_strength <= 2.0(%f)",myName,common_strength))
common_gain = Default(common_gain, true) # enable common cont strength, default true
gain_strength = Float(Default(gain_strength,0.0)) # manual gain strength
Assert(0.0 <= gain_strength <= 2.0,RT_String("%s0.0 <= gain_strength <= 2.0(%f)",myName,gain_strength))
common_cont = Default(common_cont, true) # enable common cont strength, default true
cont_strength = Float(Default(cont_strength,0.0)) # manual cont strength
Assert(0.0 <= cont_strength <= 2.0,RT_String("%s0.0 <= cont_strength <= 2.0(%f)",myName,cont_strength))
common_rpow = Default(common_rpow, true) # enable common cont strength, default true
rpow_strength = Float(Default(rpow_strength,0.0)) # manual rpow strength
Assert(0.0 <= rpow_strength <= 2.0,RT_String("%s0.0 <= rpow_strength <= 2.0(%f)",myName,rpow_strength))
common_bias = Default(common_bias, true) # enable common cont strength, default true
bias_strength = Float(Default(bias_strength,0.0)) # manual bias strength
Assert(0.0 <= bias_strength <= 2.0,RT_String("%s0.0 <= bias_strength <= 2.0(%f)",myName,bias_strength))

#---------- Specify the source rectangle under scrutiny, x,y,w,h are now type Int

x = int( Width * x)
y = int( Height * y)
w = int(-Width * w)
h = int(-Height * h)

#--------- RGB color space process

RGB32_clip = (!isRGB32(clip)) ? ConvertToRGB32(clip, matrix=matrix) : clip

CWID=72 CHIT=24 #69 21 # display Width and Height in Subtitle characters
MinWid=CWID*10 MinHit=CHIT*20 # RT_Subtitle required width height in pixels (fixed font size is 10x20)
TooSmall=(Width<MinWid || Height<MinHit)

RedStr = (TooSmall) ? "Red values :\n" : "\a2Red values\a- :\n"
GrnStr = (TooSmall) ? "Green values :\n" : "\a4Green values\a- :\n"
BluStr = (TooSmall) ? "Blue values :\n" : "\a1Blue values\a- :\n"

# Use same string at each frame.
Fmt=
\ "\nChannels averages average : %7.3f Common strength :%7.3f\n" +
\ RedStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " R_bias=%7.3f : R_gain =%7.3f : R_cont =%.3f : R_rpow=%.3f\n\n" +
\ GrnStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " G_bias=%7.3f : G_gain =%7.3f : G_cont =%.3f : G_rpow=%.3f\n\n" +
\ BluStr +
\ "Departure : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ "Finish : Average=%7.3f : Min/max=%-3d : Min=%-3d : Max=%-3d\n" +
\ " B_bias=%7.3f : B_gain =%7.3f : B_cont =%.3f : B_rpow=%.3f\n\n" +
\ "Channels averages average : %7.3f "
Bernardd is offline   Reply With Quote
Old 20th November 2017, 17:52   #13  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
Script last part
Quote:

GSCript("""
# Nested Low level Function, Called per frame via GScriptClip(), RGB32 ONLY
Function RGBAdapt_awb_process_Lo(clip clp,String Fmt,bool show_info,int x,int y,int w,int h,
\ float threshold, bool auto_strength, float common_strength,
\ bool common_gain, bool common_cont, bool common_rpow, bool common_bias,
\ float gain_strength, float cont_strength, float rpow_strength, float bias_strength,
\ Bool TooSmall,Int CWid,Int CHit) {

clp # Last = Input RGB32 clp clip.

# n = current_frame # n is current_frame, can use in RT_Stats to access frames relative to current. Not currently Used.

#---------- Channels datas extraction and adjustement factors calculation

Last.RT_RgbChanStats(x=x,y=y,w=w,h=h,threshold=threshold,chan=-1,flgs= 1+2+4+8+16, Prefix="RCS_")

blank_clip = RCS_MinMaxDiff_0 + RCS_MinMaxDiff_1 + RCS_MinMaxDiff_2 # one color clip detection to disable auto white balance

if (auto_strength)
{ave = (RCS_Ave_0+RCS_Ave_1+RCS_Ave_2)/3.0
minmax= (RCS_Max_0+RCS_Max_1+RCS_Max_2+RCS_Min_0+RCS_Min_1+RCS_Min_2)/3.0
common_strength = (ave+minmax)/(128.0+255.0)}
else
{common_strength = common_strength}

# Leave RCS_ values as original (avoid repeat function call in Show_info), new variables without RCS_ prefix, avoid div by zero.
MinMaxDiff_0 = Max(RCS_MinMaxDiff_0, 0.00001)
MinMaxDiff_1 = Max(RCS_MinMaxDiff_1, 0.00001)
MinMaxDiff_2 = Max(RCS_MinMaxDiff_2, 0.00001)

#---------- Gain process

if (common_gain) {gain_strength = common_strength}# else {gain_strength = gain_strength}

r_gain = 1.0 + (255.0/MinMaxDiff_0 - 1.0) * gain_strength
r_gain_bias = -RCS_Min_0 * r_gain *gain_strength
g_gain = 1.0 + (255.0/MinMaxDiff_1 - 1.0) * gain_strength
g_gain_bias = -RCS_Min_1 * g_gain * gain_strength
b_gain = 1.0 + (255.0/MinMaxDiff_2 - 1.0) * gain_strength
b_gain_bias = -RCS_Min_2 * b_gain * gain_strength

#------ Contrast process

# Cont is dangerous, because it can overshoot light and dark, but it is necessary to help to find good correction for very big
# color cast.

if (common_cont) {cont_strength = common_strength}

r_cont = 1.0 + (r_gain - 1.0) * cont_strength
r_cont_max = RCS_Max_0 * r_gain + r_gain_bias + (r_cont - 1) * (RCS_Max_0 - 128)
r_cont_bias = (255 - r_cont_max) * cont_strength

g_cont = 1.0 + (g_gain - 1.0) * cont_strength
g_cont_max = RCS_Max_1 * g_gain + g_gain_bias + (g_cont - 1) * (RCS_Max_1 - 128)
g_cont_bias = (255 - g_cont_max) * cont_strength

b_cont = 1.0 + (b_gain - 1.0) * cont_strength
b_cont_max = RCS_Max_2 * b_gain + b_gain_bias + (b_cont - 1) * (RCS_Max_2 - 128)
b_cont_bias = (255 - b_cont_max) * cont_strength

r_bias = r_gain_bias +r_cont_bias g_bias = g_gain_bias +g_cont_bias b_bias = b_gain_bias + b_cont_bias

#----gamma args calculation in accordance with gray world theory

# In gray world theory, in YUV range, we increase or decrease average value to ref = 128.0, but in RGB range
# ref = average of channel average values is better.
# With contrast use, average of channel average value after gain process without cont process give a better picture light.

# In gamma process, to incresae or decrease average value, we use gamma args. To find this gamma args, we
# solve this equation ref = pow(average value/255.0,1/gamma args)

ref = (RCS_Ave_0 * r_gain + r_gain_bias + RCS_Ave_1 * g_gain + g_gain_bias + RCS_Ave_2 * b_gain + b_gain_bias)/3.0

if (common_rpow) {rpow_strength = common_strength}

r_rpow = 1 + (log((RCS_Ave_0 * r_gain + r_gain_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
r_rpow = Min (4.0, Max (r_rpow, 0.1))
g_rpow = 1 + (log((RCS_Ave_1 * g_gain + g_gain_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
g_rpow = Min (4.0, Max (g_rpow, 0.1))
b_rpow = 1 + (log((RCS_Ave_2 * b_gain + b_gain_bias)/255.0)/log(ref/255.0) - 1) * rpow_strength
b_rpow = Min (4.0, Max (b_rpow, 0.1))

#--------- bias gain cont in RGBadapt args range

r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))
r_gain = Min (8.0, Max (r_gain, -8.0)) g_gain = Min (8.0, Max (g_gain, -8.0)) b_gain = Min (8.0, Max (b_gain, -8.0))
r_cont = Min (8.0, Max (r_cont, -8.0)) g_cont = Min (8.0, Max (g_cont, -8.0)) b_cont = Min (8.0, Max (b_cont, -8.0))

#---------- bias corrections in accordance with gray world theory
#----------- bias corrections extraction and calcul
# ssS, Create and measure temp clip

TempC=clp.RGBAdapt(R_bias = r_bias, R_Gain = r_gain, R_Cont = r_cont, R_rpow = r_rpow,
\ G_bias = g_bias, G_Gain = g_gain, G_Cont = g_cont, G_rpow = g_rpow,
\ B_bias = b_bias, B_Gain = b_gain, B_Cont = b_cont, B_rpow = b_rpow)

TempC.RT_RgbChanStats(x=x,y=y,w=w,h=h,threshold=threshold,chan=-1,flgs=16,Prefix="TMP_") ### Use TMP_ prefix HERE

# Ref for bias corrections always calculated with gain output, because is more light than calculated with new extracted channels average values

if (common_bias) {bias_strength = common_strength}

dr = (ref - TMP_Ave_0) * bias_strength dg = (ref - TMP_Ave_1) * bias_strength db = (ref - TMP_Ave_2) * bias_strength

r_bias = (r_gain_bias + r_cont_bias + dr) g_bias = (g_gain_bias + g_cont_bias + dg) b_bias = (b_gain_bias + b_cont_bias + db)
r_bias = Min (512.0, Max (r_bias, -512.0)) g_bias = Min (512.0, Max (g_bias, -512.0)) b_bias = Min (512.0, Max (b_bias, -512.0))

#------------ AWB output with gain cont rpow and bias process
# now change for real

(blank_clip==0)
\ ? clp
\ : clp.RGBAdapt(R_bias=r_bias,R_Gain=r_gain,R_Cont=r_cont,R_rpow=r_rpow,
\ G_bias=g_bias,G_Gain=g_gain,G_Cont=g_cont,G_rpow=g_rpow,
\ B_bias=b_bias,B_Gain=b_gain,B_Cont=b_cont,B_rpow=b_rpow)

if(show_info) {
#--------- final RGB values extraction for display
# Use different 'FIN_' Prefix so as not to destroy original variables

Last.RT_RgbChanStats(x = x, y = y, w = w, h = h, threshold = threshold, chan = -1, flgs = 1+2+4+8+16,Prefix="FIN_")

S=RT_String(Fmt,
\ (RCS_Ave_0+RCS_Ave_1+RCS_Ave_2)/3.0,common_strength,
\
\ RCS_Ave_0, RCS_MinMaxDiff_0, RCS_Min_0, RCS_Max_0,
\ FIN_Ave_0, FIN_MinMaxDiff_0, FIN_Min_0, FIN_Max_0,
\ r_bias, r_gain,r_cont,r_rpow,
\
\ RCS_Ave_1, RCS_MinMaxDiff_1, RCS_Min_1, RCS_Max_1,
\ FIN_Ave_1, FIN_MinMaxDiff_1, FIN_Min_1, FIN_Max_1,
\ g_bias, g_gain,g_cont,g_rpow,
\
\ RCS_Ave_2, RCS_MinMaxDiff_2, RCS_Min_2, RCS_Max_2,
\ FIN_Ave_2, FIN_MinMaxDiff_2, FIN_Min_2, FIN_Max_2,
\ b_bias,b_gain,b_cont,b_rpow,
\
\ (FIN_Ave_0 + FIN_Ave_1 + FIN_Ave_2 )/3, Esc=(TooSmall)?0:1)

(TooSmall)
\ ? Last.Subtitle(S,Font="Courier New",lsp=0,text_color=$FFFF00,halo_color=$0,size=height/float(CHIT),
\ Font_width=width/FloaT(CWID))
\ : Last.RT_Subtitle("%s",S)
} # End ShowInfo
Return Last
} # End, RGBAdapt_awb_process_Lo()

# GScriptClip, Calling Low level Function RGBAdapt_awb_process_Lo() at each frame.
# Named ARGS variables at current script level, are imported into GScriptClip script, and passed as args to RGBAdapt_awb_process_Lo().
ARGS="Fmt,show_info,x,y,w,h,threshold,"+
\ " auto_strength, common_strength,"+
\ " common_gain, common_cont, common_rpow, common_bias,"+
\ " gain_strength, cont_strength, rpow_strength, bias_strength,"+
\ " TooSmall,CWid,CHit"

RGB32_clip.GScriptClip("RGBAdapt_awb_process_Lo(last,"+ARGS+")", local=true, args=ARGS)

# Do border outside of Scriptclip.
if(show_scrutinized) {
Level = 100 # 0 (Off) -> 257 (Full)
MarkColor = $00FF00
#-------- display scrutinized area
scrutinized_green = Last.BlankClip(width = Width-x+w, height = height-y+h, color=MarkColor)
scrutinized_mask = scrutinized_green.Blankclip(color=$0).LetterBox(2,2,2,2,$FFFFFF)
Layer(last,scrutinized_green.Mask(scrutinized_mask),x=x,y=y,level=Level)
} # End show_scrutinized
""")
Return (clip.isYV12) ? ConvertToYV12(last, matrix=matrix) : last # Return original colorspace, YV12 or RGB32
}

Function AWB_Func(clip clip, string "matrix",bool "show_scrutinized", bool "show_info", float "x", float "y", float "w", float "h",
\ float "threshold", bool "auto_strength", float "common_strength",
\ bool "common_gain", bool "common_cont", bool "common_rpow", bool "common_bias",
\ float "gain_strength",float "cont_strength", float "rpow_strength", float "bias_strength",
\ bool "Comparison") {

# Clip MUST be YV12 or RGB32. Always returns SAME colorspace as input.
Gscript("""
clip
output=clip.RGBAdapt_Awb_Process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,x=x,y=y,w=w,h=h,threshold=threshold,
\ auto_strength = auto_strength, common_strength = common_strength,
\ common_gain = common_gain, common_cont = common_cont, common_rpow = common_rpow, common_bias = common_bias,
\ gain_strength=gain_strength, cont_strength=cont_strength, rpow_strength=rpow_strength, bias_strength=bias_strength)
if (!Default(Comparison,false)) {
output
} else {
# Here, Clip is either RGB32 or YV12.
# Ensure RGB32 for all calls to RGBAdapt_Awb_Process (Only convert input at most once)
RGB_Clip = (Clip.IsYV12) ? clip.ConvertToRGB32(matrix=matrix) : clip
only_gain = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h, threshold=threshold, auto_strength = true,common_cont = false,common_rpow = false,
\common_bias = false)
without_cont_rpow = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h,threshold=threshold, auto_strength = true, common_cont = false, common_rpow = false)
without_contrast = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h,threshold=threshold, auto_strength = true,common_cont = false)
only_gain_full = RGB_Clip.RGBAdapt_awb_process(matrix=matrix, show_scrutinized=show_scrutinized, show_info=show_info,
\ x=x, y=y, w=w, h=h,threshold=threshold, auto_strength =false, common_strength = 1.0,
\ common_cont = false,common_rpow = false,common_bias = false)
without_cont_rpow_full = RGB_Clip.RGBAdapt_awb_process(matrix=matrix,show_scrutinized=show_scrutinized,show_info=show_info,
\ x=x,y=y,w=w,h=h,threshold=threshold, auto_strength =false, common_strength = 1.0,
\ common_cont = false, common_rpow = false)
full = RGB_Clip.RGBAdapt_awb_process(matrix=matrix, show_scrutinized=show_scrutinized, show_info=show_info,
\ x=x, y=y, w=w, h=h,threshold=threshold, auto_strength = false, common_strength = 1.0)

YV12_Clip = (clip.IsRGB32) ? clip.ConvertToYV12(matrix=matrix) : clip
colorYUV_AWB = YV12_Clip.ColorYUV(autowhite = true)

# Convert clips to original Input ColorSpace.
if(clip.IsRGB32) {
colorYUV_AWB = colorYUV_AWB.ConvertToRGB32(matrix=matrix)
} else {
only_gain = only_gain.ConvertToYV12(matrix=matrix)
without_cont_rpow = without_cont_rpow.ConvertToYV12(matrix=matrix)
without_contrast = without_contrast.ConvertToYV12(matrix=matrix)
only_gain_full = only_gain_full.ConvertToYV12(matrix=matrix)
without_cont_rpow_full = without_cont_rpow_full.ConvertToYV12(matrix=matrix)
full = full.ConvertToYV12(matrix=matrix)}

#~ contrast_label=(cont_strength==0.0) ? "without contrast"
#~ \ : (cont_strength>0.0) ? "with contrast"
#~ \ : "contrast in accordance with threshold"

STK1 = StackHorizontal(
\ only_gain.AddBorders(0,20,0,0,color=$0).Subtitle("only gain "),
\ without_cont_rpow.AddBorders(0,20,0,0,color=$0).Subtitle("only gain and bias without contrast and rpow"),
\ without_contrast.AddBorders(0,20,0,0,color=$0).Subtitle("gain rpow and bias process without contrast"))
STK2 = StackHorizontal(
\ clip.AddBorders(0,20,0,0,color=$0).Subtitle("original"),
\ colorYUV_AWB.AddBorders(0,20,0,0,color=$0).Subtitle("As a reminder, classical ColorYUV awb"),
\ output.AddBorders(0,20,0,0,color=$0).Subtitle ("Selected output"))
STK3 = StackHorizontal(
\ only_gain_full.AddBorders(0,20,0,0,color=$0).Subtitle("only gain with contrast with fixed strength = 1.0"),
\ without_cont_rpow_full.AddBorders(0,20,0,0,color=$0).Subtitle("only gain and bias without contrast and rpow with fixed strength = 1.0"),
\ full.AddBorders(0,20,0,0,color=$0).Subtitle("default with fixed common strength = 1.0"))
StackVertical(STK1,STK2,STK3)
} # End, if
""") # End GScript
Return Last # Return Original ColorSpace
}

Last edited by Bernardd; 20th November 2017 at 17:57.
Bernardd is offline   Reply With Quote
Old 20th November 2017, 18:14   #14  |  Link
Sachin
Registered User
 
Join Date: Nov 2017
Location: India
Posts: 11
Bernard
Thank you very much
Sachin is offline   Reply With Quote
Old 29th January 2018, 21:15   #15  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
New script version.

Five ways for color cast correction.
action with gain,
action with contrast,
action with rpow,
acion with spow,
action with bias.
This five actions can work together or independantly. Each action have thus a tunable power strength.

In default mode, the script use gain, contrast, rpow and bias process. It compute a strength weighting
factor for each actions. This mode give often readable results for many videos with a little color cast.
The operator can refine the result with manual mode of each action (to desable contrast can be a good idea).

With big color cast, the operator can desable the automatic strength weighting factor mode to use the
whole correction of each process, it also enable spow process.

The script have always a comparison display mode to help to find the better combination of the five actions.
This mode show nine output of the video.
Top, without contrast action, in automatic strength weighting factor strength mode, you have from rigth
to left gain action only, gain and bias actions, followed by gain, rpow and bias actions.
Middle, from rigth to left, original input, AutoWhite ColorYUV process, and the tuned script output.
Bottom, from rigth to left, with strength weighting factor equal to 1.0,
gain action only, gain and bias actions, followed by gain, contrast, rpow and bias actions.

Comment
If you use AvsPmod, you can uncomment lines 45 to 72 to have UserSliders facility.
They are now two automatic strength weigthing factors. One for gain and contrast process : (channel min average + channel
max average)/255 and one for gamma and bias process channel average average/128.

The script in attachments

Bernard
Attached Files
File Type: txt RGBAdapt_Awb_Process v 2018 jan.txt (57.6 KB, 39 views)

Last edited by Bernardd; 16th February 2018 at 17:32. Reason: delete dropbox link
Bernardd is offline   Reply With Quote
Old 4th February 2018, 13:02   #16  |  Link
ABDO
Registered User
 
Join Date: Dec 2016
Posts: 65
the best Automatic white balance i have ever use,thanks @Bernardd.
ABDO is offline   Reply With Quote
Old 16th February 2018, 17:31   #17  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
New script version with automatic white balance improved in hight light.

Six ways for color cast correction.
action with gain,
action with contrast,
action with bias rpow mix,
action with spow,
action with final bias.
This six actions can work together or independantly. Each action have thus a tunable power strength.

In default mode, the script use gain, contrast, bias rpow mix, spow and final bias process.
It compute a strength weighting factor for each actions. This mode give often readable results for many videos.

The operator can refine the result with manual mode of each action. In first action i suggest to desable the contrast.
After you can use the comparison display mode, which help to find the better combination of the six actions.

Comment
If you use AvsPmod, you can uncomment lines 46 to 77 to have UserSliders facility.

The script here
and here https://www.dropbox.com/s/qft9f4fzrp...20fev.avs?dl=0

Bernard
Attached Files
File Type: txt RGBAdapt_Awb_Process v 2018 fev.txt (62.4 KB, 10 views)
Bernardd is offline   Reply With Quote
Old 2nd March 2018, 11:46   #18  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
Hello,
New script version which improve process.

First in past i have used a tip to control strength of gain, contrast and gamma process. Thus when i tuned strength to 0.0
gain, contrast and gamma values were 1.0 (neutral). When i tuned strength to 1.0, gain, contrast and gamma values were the
computed values from RGB channels datas. For example the formula for gain was :
gain = 1.0 + (255.0/MinMaxDiff_0 - 1.0) * gain_strength
In manual mode this tip is not a problem, the operator choose the good gain_strength value. But in past, in automatic mode,
i calculated a gain_strength value based on RGB channels datas to decrease, to ponderate the process strength and in this case
the formula is not accurate 1.0 + (255.0/MinMaxDiff_0 - 1.0) * gain_strength is not (255.0/MinMaxDiff_0) * gain_strength, when
gain_strength >0.0 and < 1.0.

Now i used this formula gain = (255.0/MinMaxDiff_0) * (ponderate_factor + gain_strength)
gain_strength is manual adujst arg in range from -1.0 to 1.0 with default 0.0

With the last formulas i have some problem of luma. Thus i was obliged to base the bias calcul on average of RGB channels
averages after gain to recover readable something. With accurate formulas, no luma problem. Thus all process use the RGB
channels values of original clip.

Thus the new script is for color cast correction with five and half process.
action with gain,
action with contrast,
action with one bias and rpow mix,
action with spow,
and the half,only if contrast is enable, action with one final bias to recover luma. (Contrast increase color saturation but
also decrease luma.)

This actions can work together or independantly.

The operator can enable or desable gain, contrast, rpow and spow process with boolean switchs.
He can also adjust the computed strength of gain and contraste with theire strength args.
Bias and Gamma (rpow and spow) process are auto mixed in default mode. The operator can desable this automatic process with
a boolean switch. In this case the operator can tune the bias gamma mix percentage with one arg.
In manual mix mode percentage = 0.0 traduce only gamma process, 1.0 only bias.
For inflexion point of Spow curve, the script compute one automatic spmid by RGB channels, but the operator can adjust these
spmid with a spmid strength arg.

One arg stay always manual. "pord" equal false (default) rpow corrections are computed before spow corrections, true inverse

Gain bias formulas are classic formulas. Gamma formula is a mathematical application of grey world theory. Nota, gain and contrast
are having the same formula, rpow and spow have the same formula.

Automatic ponderation factor for gain and contrast, automatic bias gamma mixed percentage and spmid have formulas choosed after
many personnal tests.

This formulas are choosed for big colors casts like lena or tahiti clip, but i think they give readable output for low colors
casts. But for big colors casts with washed colors, the spmid formula is not the best. In this case i suggest first to decrease the
spmid strength and after to try to adjust bias gamma mix in manual mode.

Below some samples

Lena with default mode and comparaison display and RgbAdapt graffer to show curves.

https://www.dropbox.com/s/cizhhta89k...aison.jpg?dl=0

https://www.dropbox.com/s/4f1t8qb4gw...affer.jpg?dl=0

Tahiti clip with default mode. On this sample we can see problem with contrast. Contrast is necessary to recover color, but we
loose some details in the dark. At the end, red is a little magenta. A little hue with Tweak function can solve this look.
https://youtu.be/y4LSb0pcTsU

Disneyland park. on left half original, on right half default without contrast and on right without contrast but with
decreased spmid strength to 0.6. I do'nt suggest that default without contrast and 0.6 spmid is the good combination, but it is
very fast to find.
https://youtu.be/x6oVh5PmTGk

Comment
If you use AvsPmod, you can uncomment lines 43 to 70 to have UserSliders facility.

The script in attachment
and here https://www.dropbox.com/s/j02xhirllh...20mar.avs?dl=0
Attached Files
File Type: txt RGBAdapt_Awb_Process v 2018 mar.txt (57.3 KB, 23 views)
Bernardd is offline   Reply With Quote
Old 30th June 2018, 23:07   #19  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
Hello
New script version. Better luma process.
It is a manual white balance, you must tune the args.

The script args are :

comparison = boolean arg to show differents settings output
show_scrutinized = boolean arg to show the scrutinized aera
show_info = boolean arg to show extracted and comptuted datas

matrix = "Rec601" or "Rec709" to choice the color conversion matrix
x = float arg to specify the left of scrutinized aera
Y = float arg to specify the top of scrutinized aera
w = float arg to specify the right of scrutinized aera
h = float arg to specify the bottom of scrutinized aera

threshold = float arg to specify extreme pixels percentage to be ignored when datas extraction

gain_strength = float arg to enable gain process and increase his strength
cont_strength = float arg to enable contrast process and increase his strength
cont_adapt = float arg to adapt contrast bias
bias_gamma = boolean arg to enable bias and gamma white balance process
bias_strength = float arg to enable bias process and increase his strength
gamma_strength = float arg to enable gamma process and increase his strength
cont_adapt2 = is the same arg as cont_adapt, but its vlaue is used when bias and gamma white balance is enable
spow = boolean arg to enable spow process
pord = boolean arg to secify order of rpow and spow process
spmid_strength = float arg to adapt spimd
temperature = float arg to increase or decrease color temperature

The script calculate for each color channel,
- the classic autogain with a gain bias to keep the value between 0 to 255
- the contrast, with gain formula and a cont bias to aviod a visual bad offset
- a bias to keep the luma value after gain and or contrast application
- in accordance with the grey world theory a bias to get the same value of color channel average
- in accordance with the grey world theory a rpow float number
- a spow float number with the rpow formula
- a spmid number to specify inflexion point of the s curve

Cont_adapt, cont_adapt2, bias_gamma, pord and temperature are not computed. They are operator choices.

The operator can modify, adjust the computed results by increasing or decreasing gain, contrast, bias and gamma strengths and cont adapt.
The operator can choice the combination of process. Gain, contrast, bias and gamma strengths desable process when their values are null.

Nota : For gain and contrast strengths = 0.0, gain and contrast factors = 1.0 and gain bias and contrast bias = 0.0.
But, for gain and contrast strengths = 0.1, gain and contrast factors are near to 1.0, but gain and contrast bias are not null. For sample, if
the min value of one color channel is 100, the bias for gain is -100.

The perform of this script is the contrast bias use. The operateur can tune cont_adapt2 (or cont_adapt if only gain and contrasts process are
selected) to get the best contrast bias.
For some videos, it is possible to get a readable white balance with only gain and contrast process.
For other video, you must use classical bias and gamma process. The arg tunes are manual

With the boolean arg bias_gamma, you can make a fast comparison between gain and contrast result and result of combination of gain, contrast, bias and gamma .

The default args give a readable output with "lena" color cast sample picture. But it can be better. First decrease or increase cont-adapat2.

The script have always a comparison display mode to help to find the better combination of actions.
This mode show nine output of the video.
Top, from left to right, gain action only, gain and bias actions, followed by gain, rpow and bias actions.
Middle, from left to right, original input, AutoWhite ColorYUV process, and the tuned script output.
Bottom, from left to right, default modes without gain, and without cont, default modes without gain and default modes all process.

Comment
If you use AvsPmod, you can uncomment lines 45 to 76 to have UserSliders facility.

The script here in attachment
and here https://www.dropbox.com/s/lhvwqufa8h...0juil.avs?dl=0


Bernard
Attached Files
File Type: txt RGBAdapt_Awb_Process v 2018 juil.txt (54.4 KB, 11 views)

Last edited by Bernardd; 30th June 2018 at 23:10.
Bernardd is offline   Reply With Quote
Old 17th September 2018, 15:44   #20  |  Link
Bernardd
Registered User
 
Join Date: Jan 2012
Location: Toulon France
Posts: 213
Hello,

The script with two automatic modes and one manual.
The first automatic mode use only gain and contrast process, sometimes for white balance it is enough.
The second automatic mode use gain, contrast, bias and gamma process. In this mode you can adjust gamma S curves process action to refine the white balance.
In manual mode you tune separately each process actions.

The script args are :
1- for display tunings
- comparison , default = false, to compare different process selection outputs :
-------------------Top, from left to right, full gain an contrast action,full contrast action, followed by automatic gain and contrast actions.
-------------------Middle, from left to right, original input, AutoWhite ColorYUV process, and the tuned script output.
-------------------Bottom, from left to right, automatic mode without rpow, automatic modes without spow and automatic mode all process.
- show_scrutinized, default = false, to select the area scrutinized by RT_Stat plugin for data extraction
- show_info, default = false, to see extracted datas and process args tune

- matrix, defaut = "Rec601", to give the video color space matrix
- x, default = 0.1, to specify the source rectangle under scrutiny by RT_Stat plugin for data extraction
- Y, default = 0.1, see RT_STAT doc
- w, default = 0.1
- h, default = 0.1

- threshold, default = 0.1, to specify extreme pixels percentage to be ignored when datas extraction (see RT_STAT doc)

2- automatic white balance preset tunings

- mode, default = "auto", in this case all process are used in automatic, if "gain_&_cont" only gain and contrast are used in automatic,
if "manual" you tune separately each process
- rpow, default = true, only efficiency in mode "auto", you can enable or desable the rpow process,
- spow, default = true, only efficiency in mode "auto", you can enable or desable the rpow process,
- spow_adjust, default = 0.0, float from -1.0 to 1.0, only efficiency in mode "auto", you can adjust the automatic computed spow strength to refine spow process. If value = 0.0 no computed spow strength have not change.

3- manual white balance tunings
- gain_strength, default = 0.5, float from 0.0 to 1.0, to tune gain process strength. If value = 0.0 no gain process use.
- cont_strength, default = 0.5, float from 0.0 to 1.0, to tune contrast process strength. If value = 0.0 no conttrast process use.
- g_c_bias_adapt, default = 0.5, float from 0.0 to 1.0, to adjust the automatic bias computed when gain and or contrast are applied.
If value = 0.0 computed gain and cont bias = 0.0.
- bias_strength, default = 0.5, float from 0.0 to 1.0, to tune bias process strength. This bias is a computed bias in accordance with grey world theory for color balance. If value = 0.0 no bias process use.
- rpow_strength, default = 0.5, float from 0.0 to 1.0, to tune rpow process strength. This computed rpow is the application of the grey world theory for color balance to gamma space. Explanation in script comment. If value = 0.0 no rpow process use.
- spow_strength, default = 1.5, float from 0.0 to 2.0, to tune spow process strength. Like rpow proces but with S curve.
If value = 1.0 no spow process use.

4- spow process's specifics tunes in automatic or manual mode, if spow process is enable
- pord, default = false, priority for rpow or spow process, see RGBAdapt doc.
- spmid_strength, default = 1.0, float from 0.0 to 1.0, you can adjust the automatic computed spmid strength to refine spow process


In this script, gain formula and grey world bias formula are classical. The other formulas are empirical, i have searched formulas to mix maximal,
minimal and average values of each RGB channel RGB to :
- do not use too much the autogain process and
- get best results with almong videos clips plubished on this forum like
here https://forum.doom9.org/showpost.php...7&postcount=83
or found on WDW plublication https://forum.doom9.org/showpost.php...&postcount=924

The problem of this method is to found a good mix of datas to get always the good S curve correction. In fact, the Max, Min and average values of RGB channels are not enough to describe a color channel histogram with two or more pic values. Thus i have jut found one formula for gentle videos.
A manual adjust of Spow correction is often necessary. You can make it by tuning spow_adjust and or spmid args.

Each video is specific, each scene is specific, a tip is to look at the comparison display output of the script to find the best combination of process.
Often, if the automatic mode without spow seem to be the best, you have interest before to desable spow, to tune spow_adjust and or spmid tune. With this display you can find some scene like below, which have a good result with only manual contrast use (result with full gain and contrast seem better, but you have no reserve for add autogain and more saturation).

https://www.dropbox.com/s/omvsv5aj7u...00082.jpg?dl=0

Comment
If you use AvsPmod, you can uncomment lines 49 to 81 to have UserSliders facility.

The script here in attachment
and here https://www.dropbox.com/s/kxwctnxg5q...0sept.avs?dl=0

Bernard
Attached Files
File Type: txt RGBAdapt_Awb_Process v 2018 sept.txt (61.8 KB, 16 views)

Last edited by Bernardd; 18th September 2018 at 19:24.
Bernardd is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 20:55.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.