[PATCH v2 17/17] libipa: awb_bayes: Change the probabilities from log space into linear space

Paul Elder paul.elder at ideasonboard.com
Mon Jan 27 12:47:55 CET 2025


On Thu, Jan 23, 2025 at 12:41:07PM +0100, Stefan Klug wrote:
> The original code used to specify the probabilities in log space and
> scaled for the RaspberryPi hardware with 192 AWB measurement points.
> This is reasonable as the whole algorithm makes use of unitless numbers
> to prefer some colour temperatures based on a lux level. These numbers
> are then hand tuned with the specific device in mind.
> 
> This has two shortcomings:
> 
> 1. The linear interpolation of PWLs in log space is mathematically
>    incorrect. The outcome might still be ok, as both spaces (log and
> linear) are monotonic, but it is still not "right".
> 
> 2. Having unitless numbers gets more error prone when we try to
>    harmonize the behavior over multiple platforms.
> 
> Change the algorithm to interpret the numbers as being in linear space.
> This makes the interpolation mathematically correct at the expense of a
> few log operations.
> 
> To account for that change, update the numbers in the tuning example
> file with the linear counterparts scaled to one AWB zone measurement.
> 
> Signed-off-by: Stefan Klug <stefan.klug at ideasonboard.com>

Reviewed-by: Paul Elder <paul.elder at ideasonboard.com>

> 
> ---
> 
> Changes in v2:
> - Added this commit
> ---
>  src/ipa/libipa/awb.cpp           |  5 +++--
>  src/ipa/libipa/awb_bayes.cpp     |  8 ++++++--
>  utils/tuning/config-example.yaml | 12 ++++++------
>  3 files changed, 15 insertions(+), 10 deletions(-)
> 
> diff --git a/src/ipa/libipa/awb.cpp b/src/ipa/libipa/awb.cpp
> index 62b69dd96238..6157bd436183 100644
> --- a/src/ipa/libipa/awb.cpp
> +++ b/src/ipa/libipa/awb.cpp
> @@ -57,8 +57,9 @@ namespace ipa {
>   * applied. To keep the actual implementations computationally inexpensive,
>   * the squared colour error shall be returned.
>   *
> - * If the awb statistics provide multiple zones, the sum over all zones needs to
> - * calculated.
> + * If the awb statistics provide multiple zones, the average of the individual
> + * squared errors shall be returned. Averaging/normalizing is necessary so that
> + * the numeric dimensions are the same on all hardware platforms.
>   *
>   * \return The computed error value
>   */
> diff --git a/src/ipa/libipa/awb_bayes.cpp b/src/ipa/libipa/awb_bayes.cpp
> index 6b88aebeffb5..5f43421e14c7 100644
> --- a/src/ipa/libipa/awb_bayes.cpp
> +++ b/src/ipa/libipa/awb_bayes.cpp
> @@ -235,6 +235,10 @@ int AwbBayes::readPriors(const YamlObject &tuningData)
>  
>  		auto &pwl = priors[lux];
>  		for (const auto &[ct, prob] : ctToProbability) {
> +			if (prob < 1e-6) {
> +				LOG(Awb, Error) << "Prior probability must be larger than 1e-6";
> +				return -EINVAL;
> +			}
>  			pwl.append(ct, prob);
>  		}
>  	}
> @@ -324,7 +328,7 @@ double AwbBayes::coarseSearch(const ipa::Pwl &prior, const AwbStats &stats) cons
>  		double b = ctB_.eval(t, &spanB);
>  		RGB<double> gains({ 1 / r, 1.0, 1 / b });
>  		double delta2Sum = stats.computeColourError(gains);
> -		double priorLogLikelihood = prior.eval(prior.domain().clamp(t));
> +		double priorLogLikelihood = log(prior.eval(prior.domain().clamp(t)));
>  		double finalLogLikelihood = delta2Sum - priorLogLikelihood;
>  
>  		errorLimits.record(delta2Sum);
> @@ -407,7 +411,7 @@ void AwbBayes::fineSearch(double &t, double &r, double &b, ipa::Pwl const &prior
>  	for (int i = -nsteps; i <= nsteps; i++) {
>  		double tTest = t + i * step;
>  		double priorLogLikelihood =
> -			prior.eval(prior.domain().clamp(tTest));
> +			log(prior.eval(prior.domain().clamp(tTest)));
>  		priorLogLikelihoodLimits.record(priorLogLikelihood);
>  		Pwl::Point rbStart{ { ctR_.eval(tTest, &spanR),
>  				      ctB_.eval(tTest, &spanB) } };
> diff --git a/utils/tuning/config-example.yaml b/utils/tuning/config-example.yaml
> index 1bbb275778dc..5593eaef809e 100644
> --- a/utils/tuning/config-example.yaml
> +++ b/utils/tuning/config-example.yaml
> @@ -7,21 +7,21 @@ general:
>    awb:
>      # Algorithm can either be 'grey' or 'bayes'
>      algorithm: bayes
> -    # Priors is only used for the bayes algorithm. They are defined in
> -    # logarithmic space. A good staring point is:
> +    # Priors is only used for the bayes algorithm. They are defined in linear
> +    # space. A good staring point is:
>      # - lux: 0
>      #   ct: [ 2000, 3000, 13000 ]
> -    #   probability: [ 1.0, 0.0, 0.0 ]
> +    #   probability: [ 1.005, 1.0, 1.0 ]
>      # - lux: 800
>      #   ct: [ 2000, 6000, 13000 ]
> -    #   probability: [ 0.0, 2.0, 2.0 ]
> +    #   probability: [ 1.0, 1.01, 1.01 ]
>      # - lux: 1500
>      #   ct: [ 2000, 4000, 6000, 6500, 7000, 13000 ]
> -    #   probability: [ 0.0, 1.0, 6.0, 7.0, 1.0, 1.0 ]
> +    #   probability: [ 1.0, 1.005, 1.032, 1.037, 1.01, 1.01 ]
>      priors:
>        - lux: 0
>          ct: [ 2000, 13000 ]
> -        probability: [ 0.0, 0.0 ]
> +        probability: [ 1.0, 1.0 ]
>      AwbMode:
>        AwbAuto:
>          lo: 2500
> -- 
> 2.43.0
> 


More information about the libcamera-devel mailing list