[v2,10/17] ipa: rkisp1: Add support for bayes AWB algorithm from libipa
diff mbox series

Message ID 20250123114204.79321-11-stefan.klug@ideasonboard.com
State Accepted
Headers show
Series
  • Add Bayesian AWB algorithm to libipa and rkisp1
Related show

Commit Message

Stefan Klug Jan. 23, 2025, 11:41 a.m. UTC
Now that libipa contains a bayes AWB algorithm, add it as supported
algorithm to the rkisp1 ipa.

The decision between the grey world algorithm and the bayesian is done
based on the "algorithm" property of the "Awb" algorithm in the tuning
file. If the lux value in the frameContext is set by the Lux algorithm
it is taken into account. If the lux value is 0 the prior likelihood
estimation gets ignored in the AWB calculations.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>

---

Changes in v2:
- Collected tags
---
 src/ipa/rkisp1/algorithms/awb.cpp | 52 +++++++++++++++++++++++--------
 1 file changed, 39 insertions(+), 13 deletions(-)

Comments

Laurent Pinchart Feb. 23, 2025, 10:56 p.m. UTC | #1
Hi Stefan,

On Thu, Jan 23, 2025 at 12:41:00PM +0100, Stefan Klug wrote:
> Now that libipa contains a bayes AWB algorithm, add it as supported
> algorithm to the rkisp1 ipa.
> 
> The decision between the grey world algorithm and the bayesian is done
> based on the "algorithm" property of the "Awb" algorithm in the tuning
> file. If the lux value in the frameContext is set by the Lux algorithm
> it is taken into account. If the lux value is 0 the prior likelihood
> estimation gets ignored in the AWB calculations.
> 
> Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
> 
> ---
> 
> Changes in v2:
> - Collected tags
> ---
>  src/ipa/rkisp1/algorithms/awb.cpp | 52 +++++++++++++++++++++++--------
>  1 file changed, 39 insertions(+), 13 deletions(-)
> 
> diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp
> index b21d0d4c03bb..55e1b43c8cd2 100644
> --- a/src/ipa/rkisp1/algorithms/awb.cpp
> +++ b/src/ipa/rkisp1/algorithms/awb.cpp
> @@ -16,6 +16,7 @@
>  
>  #include <libcamera/ipa/core_ipa_interface.h>
>  
> +#include "libipa/awb_bayes.h"
>  #include "libipa/awb_grey.h"
>  #include "libipa/colours.h"
>  
> @@ -45,13 +46,23 @@ class RkISP1AwbStats : public AwbStats
>  {
>  public:
>  	RkISP1AwbStats(const RGB<double> &rgbMeans)
> -		: rgbMeans_(rgbMeans) {}
> +		: rgbMeans_(rgbMeans)
> +	{
> +		rg_ = rgbMeans_.r() / rgbMeans_.g();
> +		bg_ = rgbMeans_.b() / rgbMeans_.g();
> +	}
>  
> -	double computeColourError([[maybe_unused]] const RGB<double> &gains) const override
> +	double computeColourError(const RGB<double> &gains) const override
>  	{
> -		LOG(RkISP1Awb, Error)
> -			<< "RkISP1AwbStats::computeColourError is not implemented";
> -		return 0.0;
> +		/*
> +		* Compute the sum of the squared colour error (non-greyness) as it
> +		* appears in the log likelihood equation.
> +		*/
> +		double deltaR = gains.r() * rg_ - 1.0;
> +		double deltaB = gains.b() * bg_ - 1.0;
> +		double delta2 = deltaR * deltaR + deltaB * deltaB;
> +
> +		return delta2;
>  	}
>  
>  	RGB<double> getRGBMeans() const override
> @@ -61,6 +72,8 @@ public:
>  
>  private:
>  	RGB<double> rgbMeans_;
> +	double rg_;
> +	double bg_;
>  };
>  
>  Awb::Awb()
> @@ -78,13 +91,30 @@ int Awb::init(IPAContext &context, const YamlObject &tuningData)
>  							 kMaxColourTemperature,
>  							 kDefaultColourTemperature);
>  
> -	awbAlgo_ = std::make_unique<AwbGrey>();
> +	if (!tuningData.contains("algorithm"))
> +		LOG(RkISP1Awb, Info) << "No awb algorithm specified."
> +				     << " Default to grey world";
> +
> +	auto mode = tuningData["algorithm"].get<std::string>("grey");
> +	if (mode == "grey") {
> +		awbAlgo_ = std::make_unique<AwbGrey>();
> +	} else if (mode == "bayes") {
> +		awbAlgo_ = std::make_unique<AwbBayes>();
> +	} else {
> +		LOG(RkISP1Awb, Error) << "Unknown awb algorithm: " << mode;
> +		return -EINVAL;
> +	}
> +	LOG(RkISP1Awb, Debug) << "Using awb algorithm: " << mode;
> +
>  	int ret = awbAlgo_->init(tuningData);
>  	if (ret) {
>  		LOG(RkISP1Awb, Error) << "Failed to init awb algorithm";
>  		return ret;
>  	}
>  
> +	const auto &src = awbAlgo_->controls();
> +	cmap.insert(src.begin(), src.end());
> +
>  	return 0;
>  }
>  
> @@ -131,6 +161,8 @@ void Awb::queueRequest(IPAContext &context,
>  			<< (*awbEnable ? "Enabling" : "Disabling") << " AWB";
>  	}
>  
> +	awbAlgo_->handleControls(controls);
> +
>  	frameContext.awb.autoEnabled = awb.autoEnabled;
>  
>  	if (awb.autoEnabled)

There's a comment a bit below that states

		/*
		 * \todo: Colour temperature reported in metadata is now
		 * incorrect, as we can't deduce the temperature from the gains.
		 * This will be fixed with the bayes AWB algorithm.
		 */

Has this been addressed, can it be removed ?

> @@ -271,14 +303,8 @@ void Awb::process(IPAContext &context,
>  	    rgbMeans.b() < kMeanMinThreshold)
>  		return;
>  
> -	/*
> -	 * \Todo: Hardcode lux to a fixed value, until an estimation is
> -	 * implemented.
> -	 */
> -	int lux = 1000;
> -
>  	RkISP1AwbStats awbStats{ rgbMeans };
> -	AwbResult awbResult = awbAlgo_->calculateAwb(awbStats, lux);
> +	AwbResult awbResult = awbAlgo_->calculateAwb(awbStats, frameContext.lux.lux);
>  
>  	activeState.awb.temperatureK = awbResult.colourTemperature;
>

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp
index b21d0d4c03bb..55e1b43c8cd2 100644
--- a/src/ipa/rkisp1/algorithms/awb.cpp
+++ b/src/ipa/rkisp1/algorithms/awb.cpp
@@ -16,6 +16,7 @@ 
 
 #include <libcamera/ipa/core_ipa_interface.h>
 
+#include "libipa/awb_bayes.h"
 #include "libipa/awb_grey.h"
 #include "libipa/colours.h"
 
@@ -45,13 +46,23 @@  class RkISP1AwbStats : public AwbStats
 {
 public:
 	RkISP1AwbStats(const RGB<double> &rgbMeans)
-		: rgbMeans_(rgbMeans) {}
+		: rgbMeans_(rgbMeans)
+	{
+		rg_ = rgbMeans_.r() / rgbMeans_.g();
+		bg_ = rgbMeans_.b() / rgbMeans_.g();
+	}
 
-	double computeColourError([[maybe_unused]] const RGB<double> &gains) const override
+	double computeColourError(const RGB<double> &gains) const override
 	{
-		LOG(RkISP1Awb, Error)
-			<< "RkISP1AwbStats::computeColourError is not implemented";
-		return 0.0;
+		/*
+		* Compute the sum of the squared colour error (non-greyness) as it
+		* appears in the log likelihood equation.
+		*/
+		double deltaR = gains.r() * rg_ - 1.0;
+		double deltaB = gains.b() * bg_ - 1.0;
+		double delta2 = deltaR * deltaR + deltaB * deltaB;
+
+		return delta2;
 	}
 
 	RGB<double> getRGBMeans() const override
@@ -61,6 +72,8 @@  public:
 
 private:
 	RGB<double> rgbMeans_;
+	double rg_;
+	double bg_;
 };
 
 Awb::Awb()
@@ -78,13 +91,30 @@  int Awb::init(IPAContext &context, const YamlObject &tuningData)
 							 kMaxColourTemperature,
 							 kDefaultColourTemperature);
 
-	awbAlgo_ = std::make_unique<AwbGrey>();
+	if (!tuningData.contains("algorithm"))
+		LOG(RkISP1Awb, Info) << "No awb algorithm specified."
+				     << " Default to grey world";
+
+	auto mode = tuningData["algorithm"].get<std::string>("grey");
+	if (mode == "grey") {
+		awbAlgo_ = std::make_unique<AwbGrey>();
+	} else if (mode == "bayes") {
+		awbAlgo_ = std::make_unique<AwbBayes>();
+	} else {
+		LOG(RkISP1Awb, Error) << "Unknown awb algorithm: " << mode;
+		return -EINVAL;
+	}
+	LOG(RkISP1Awb, Debug) << "Using awb algorithm: " << mode;
+
 	int ret = awbAlgo_->init(tuningData);
 	if (ret) {
 		LOG(RkISP1Awb, Error) << "Failed to init awb algorithm";
 		return ret;
 	}
 
+	const auto &src = awbAlgo_->controls();
+	cmap.insert(src.begin(), src.end());
+
 	return 0;
 }
 
@@ -131,6 +161,8 @@  void Awb::queueRequest(IPAContext &context,
 			<< (*awbEnable ? "Enabling" : "Disabling") << " AWB";
 	}
 
+	awbAlgo_->handleControls(controls);
+
 	frameContext.awb.autoEnabled = awb.autoEnabled;
 
 	if (awb.autoEnabled)
@@ -271,14 +303,8 @@  void Awb::process(IPAContext &context,
 	    rgbMeans.b() < kMeanMinThreshold)
 		return;
 
-	/*
-	 * \Todo: Hardcode lux to a fixed value, until an estimation is
-	 * implemented.
-	 */
-	int lux = 1000;
-
 	RkISP1AwbStats awbStats{ rgbMeans };
-	AwbResult awbResult = awbAlgo_->calculateAwb(awbStats, lux);
+	AwbResult awbResult = awbAlgo_->calculateAwb(awbStats, frameContext.lux.lux);
 
 	activeState.awb.temperatureK = awbResult.colourTemperature;