[v6,3/9] ipa: rkisp1: awb: Implement ColourTemperature control
diff mbox series

Message ID 20241219175729.293782-4-stefan.klug@ideasonboard.com
State New
Headers show
Series
  • rkisp1: Add manual colour temperature control
Related show

Commit Message

Stefan Klug Dec. 19, 2024, 5:57 p.m. UTC
There are many use-cases (tuning-validation, working in static
environments) where a manual ColourTemperature control is helpful.
Implement that by interpolating and applying the white balance gains
from the tuning file according to the requested colour temperature. If
colour gains are provided on the same request, they take precedence.
Store the colour temperature used for a given frame in the frame context
and report that in metadata.

Note that in the automatic case, the colour gains are still based on the
gray world model and the CT curve from the tuning file get ignored.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

---

Changes in v6:
- Updated commit message
- Moved retrieval of controls to the place where needed
- Output the colour temperature applied to a frame in metadata
---
 src/ipa/rkisp1/algorithms/awb.cpp | 51 +++++++++++++++++++++++--------
 src/ipa/rkisp1/ipa_context.h      |  1 +
 2 files changed, 40 insertions(+), 12 deletions(-)

Comments

Laurent Pinchart Dec. 20, 2024, 9:54 a.m. UTC | #1
Hi Stefan,

Thank you for the patch.

On Thu, Dec 19, 2024 at 06:57:20PM +0100, Stefan Klug wrote:
> There are many use-cases (tuning-validation, working in static
> environments) where a manual ColourTemperature control is helpful.
> Implement that by interpolating and applying the white balance gains
> from the tuning file according to the requested colour temperature. If
> colour gains are provided on the same request, they take precedence.
> Store the colour temperature used for a given frame in the frame context
> and report that in metadata.
> 
> Note that in the automatic case, the colour gains are still based on the
> gray world model and the CT curve from the tuning file get ignored.
> 
> Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> ---
> 
> Changes in v6:
> - Updated commit message
> - Moved retrieval of controls to the place where needed
> - Output the colour temperature applied to a frame in metadata
> ---
>  src/ipa/rkisp1/algorithms/awb.cpp | 51 +++++++++++++++++++++++--------
>  src/ipa/rkisp1/ipa_context.h      |  1 +
>  2 files changed, 40 insertions(+), 12 deletions(-)
> 
> diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp
> index e23f67a96edf..cffaa06a22c1 100644
> --- a/src/ipa/rkisp1/algorithms/awb.cpp
> +++ b/src/ipa/rkisp1/algorithms/awb.cpp
> @@ -33,6 +33,10 @@ namespace ipa::rkisp1::algorithms {
>  
>  LOG_DEFINE_CATEGORY(RkISP1Awb)
>  
> +constexpr int32_t kMinColourTemperature = 2500;
> +constexpr int32_t kMaxColourTemperature = 10000;
> +constexpr int32_t kDefaultColourTemperature = 5000;
> +
>  /* Minimum mean value below which AWB can't operate. */
>  constexpr double kMeanMinThreshold = 2.0;
>  
> @@ -44,8 +48,13 @@ Awb::Awb()
>  /**
>   * \copydoc libcamera::ipa::Algorithm::init
>   */
> -int Awb::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData)
> +int Awb::init(IPAContext &context, const YamlObject &tuningData)
>  {
> +	auto &cmap = context.ctrlMap;
> +	cmap[&controls::ColourTemperature] = ControlInfo(kMinColourTemperature,
> +							 kMaxColourTemperature,
> +							 kDefaultColourTemperature);
> +
>  	Interpolator<Vector<double, 2>> gainCurve;
>  	int ret = gainCurve.readYaml(tuningData["colourGains"], "ct", "gains");
>  	if (ret < 0)
> @@ -68,6 +77,7 @@ int Awb::configure(IPAContext &context,
>  	context.activeState.awb.gains.manual = RGB<double>{ 1.0 };
>  	context.activeState.awb.gains.automatic = RGB<double>{ 1.0 };
>  	context.activeState.awb.autoEnabled = true;
> +	context.activeState.awb.temperatureK = kDefaultColourTemperature;
>  
>  	/*
>  	 * Define the measurement window for AWB as a centered rectangle
> @@ -101,19 +111,37 @@ void Awb::queueRequest(IPAContext &context,
>  			<< (*awbEnable ? "Enabling" : "Disabling") << " AWB";
>  	}
>  
> +	frameContext.awb.autoEnabled = awb.autoEnabled;
> +
> +	if (awb.autoEnabled)
> +		return;
> +
>  	const auto &colourGains = controls.get(controls::ColourGains);
> -	if (colourGains && !awb.autoEnabled) {
> +	const auto &colourTemperature = controls.get(controls::ColourTemperature);
> +	bool update = false;
> +	if (colourGains) {
>  		awb.gains.manual.r() = (*colourGains)[0];
>  		awb.gains.manual.b() = (*colourGains)[1];
> +		/*
> +		 * \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.
> +		 */

Will we require all cameras to implement bayesian AWB ? If not, the the
controls documentation need to allow that. I suppose that
ColourTemperature will then not be reported as a settable control by the
camera, so application will know.

I'm fine clarifying the documentation on top of this series. Can you
make sure it gets done ?

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +		update = true;
> +	} else if (colourTemperature && colourGainCurve_) {
> +		const auto &gains = colourGainCurve_->getInterpolated(*colourTemperature);
> +		awb.gains.manual.r() = gains[0];
> +		awb.gains.manual.b() = gains[1];
> +		awb.temperatureK = *colourTemperature;
> +		update = true;
> +	}
>  
> +	if (update)
>  		LOG(RkISP1Awb, Debug)
>  			<< "Set colour gains to " << awb.gains.manual;
> -	}
>  
> -	frameContext.awb.autoEnabled = awb.autoEnabled;
> -
> -	if (!awb.autoEnabled)
> -		frameContext.awb.gains = awb.gains.manual;
> +	frameContext.awb.gains = awb.gains.manual;
> +	frameContext.awb.temperatureK = awb.temperatureK;
>  }
>  
>  /**
> @@ -126,8 +154,10 @@ void Awb::prepare(IPAContext &context, const uint32_t frame,
>  	 * This is the latest time we can read the active state. This is the
>  	 * most up-to-date automatic values we can read.
>  	 */
> -	if (frameContext.awb.autoEnabled)
> +	if (frameContext.awb.autoEnabled) {
>  		frameContext.awb.gains = context.activeState.awb.gains.automatic;
> +		frameContext.awb.temperatureK = context.activeState.awb.temperatureK;
> +	}
>  
>  	auto gainConfig = params->block<BlockType::AwbGain>();
>  	gainConfig.setEnabled(true);
> @@ -206,7 +236,7 @@ void Awb::process(IPAContext &context,
>  			static_cast<float>(frameContext.awb.gains.r()),
>  			static_cast<float>(frameContext.awb.gains.b())
>  		});
> -	metadata.set(controls::ColourTemperature, activeState.awb.temperatureK);
> +	metadata.set(controls::ColourTemperature, frameContext.awb.temperatureK);
>  
>  	if (!stats || !(stats->meas_type & RKISP1_CIF_ISP_STAT_AWB)) {
>  		LOG(RkISP1Awb, Error) << "AWB data is missing in statistics";
> @@ -281,9 +311,6 @@ void Awb::process(IPAContext &context,
>  
>  	activeState.awb.temperatureK = estimateCCT(rgbMeans);
>  
> -	/* Metadata shall contain the up to date measurement */
> -	metadata.set(controls::ColourTemperature, activeState.awb.temperatureK);
> -
>  	/*
>  	 * Estimate the red and blue gains to apply in a grey world. The green
>  	 * gain is hardcoded to 1.0. Avoid divisions by zero by clamping the
> diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
> index deb8c196f1b8..4b50015beee8 100644
> --- a/src/ipa/rkisp1/ipa_context.h
> +++ b/src/ipa/rkisp1/ipa_context.h
> @@ -135,6 +135,7 @@ struct IPAFrameContext : public FrameContext {
>  	struct {
>  		RGB<double> gains;
>  		bool autoEnabled;
> +		unsigned int temperatureK;
>  	} awb;
>  
>  	struct {
Stefan Klug Dec. 20, 2024, 10:07 a.m. UTC | #2
Hi Laurent,

Thank you for the review. 

On Fri, Dec 20, 2024 at 11:54:57AM +0200, Laurent Pinchart wrote:
> Hi Stefan,
> 
> Thank you for the patch.
> 
> On Thu, Dec 19, 2024 at 06:57:20PM +0100, Stefan Klug wrote:
> > There are many use-cases (tuning-validation, working in static
> > environments) where a manual ColourTemperature control is helpful.
> > Implement that by interpolating and applying the white balance gains
> > from the tuning file according to the requested colour temperature. If
> > colour gains are provided on the same request, they take precedence.
> > Store the colour temperature used for a given frame in the frame context
> > and report that in metadata.
> > 
> > Note that in the automatic case, the colour gains are still based on the
> > gray world model and the CT curve from the tuning file get ignored.
> > 
> > Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
> > Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
> > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> > 
> > ---
> > 
> > Changes in v6:
> > - Updated commit message
> > - Moved retrieval of controls to the place where needed
> > - Output the colour temperature applied to a frame in metadata
> > ---
> >  src/ipa/rkisp1/algorithms/awb.cpp | 51 +++++++++++++++++++++++--------
> >  src/ipa/rkisp1/ipa_context.h      |  1 +
> >  2 files changed, 40 insertions(+), 12 deletions(-)
> > 
> > diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp
> > index e23f67a96edf..cffaa06a22c1 100644
> > --- a/src/ipa/rkisp1/algorithms/awb.cpp
> > +++ b/src/ipa/rkisp1/algorithms/awb.cpp
> > @@ -33,6 +33,10 @@ namespace ipa::rkisp1::algorithms {
> >  
> >  LOG_DEFINE_CATEGORY(RkISP1Awb)
> >  
> > +constexpr int32_t kMinColourTemperature = 2500;
> > +constexpr int32_t kMaxColourTemperature = 10000;
> > +constexpr int32_t kDefaultColourTemperature = 5000;
> > +
> >  /* Minimum mean value below which AWB can't operate. */
> >  constexpr double kMeanMinThreshold = 2.0;
> >  
> > @@ -44,8 +48,13 @@ Awb::Awb()
> >  /**
> >   * \copydoc libcamera::ipa::Algorithm::init
> >   */
> > -int Awb::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData)
> > +int Awb::init(IPAContext &context, const YamlObject &tuningData)
> >  {
> > +	auto &cmap = context.ctrlMap;
> > +	cmap[&controls::ColourTemperature] = ControlInfo(kMinColourTemperature,
> > +							 kMaxColourTemperature,
> > +							 kDefaultColourTemperature);
> > +
> >  	Interpolator<Vector<double, 2>> gainCurve;
> >  	int ret = gainCurve.readYaml(tuningData["colourGains"], "ct", "gains");
> >  	if (ret < 0)
> > @@ -68,6 +77,7 @@ int Awb::configure(IPAContext &context,
> >  	context.activeState.awb.gains.manual = RGB<double>{ 1.0 };
> >  	context.activeState.awb.gains.automatic = RGB<double>{ 1.0 };
> >  	context.activeState.awb.autoEnabled = true;
> > +	context.activeState.awb.temperatureK = kDefaultColourTemperature;
> >  
> >  	/*
> >  	 * Define the measurement window for AWB as a centered rectangle
> > @@ -101,19 +111,37 @@ void Awb::queueRequest(IPAContext &context,
> >  			<< (*awbEnable ? "Enabling" : "Disabling") << " AWB";
> >  	}
> >  
> > +	frameContext.awb.autoEnabled = awb.autoEnabled;
> > +
> > +	if (awb.autoEnabled)
> > +		return;
> > +
> >  	const auto &colourGains = controls.get(controls::ColourGains);
> > -	if (colourGains && !awb.autoEnabled) {
> > +	const auto &colourTemperature = controls.get(controls::ColourTemperature);
> > +	bool update = false;
> > +	if (colourGains) {
> >  		awb.gains.manual.r() = (*colourGains)[0];
> >  		awb.gains.manual.b() = (*colourGains)[1];
> > +		/*
> > +		 * \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.
> > +		 */
> 
> Will we require all cameras to implement bayesian AWB ? If not, the the
> controls documentation need to allow that. I suppose that
> ColourTemperature will then not be reported as a settable control by the
> camera, so application will know.

This case happens when setting the colour gains. So making the
ColourTemperature an output only won't help here. We could stop
reporting it in metadata. But that is for later.

> 
> I'm fine clarifying the documentation on top of this series. Can you
> make sure it gets done ?
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Thanks!

Cheers,
Stefan

> 
> > +		update = true;
> > +	} else if (colourTemperature && colourGainCurve_) {
> > +		const auto &gains = colourGainCurve_->getInterpolated(*colourTemperature);
> > +		awb.gains.manual.r() = gains[0];
> > +		awb.gains.manual.b() = gains[1];
> > +		awb.temperatureK = *colourTemperature;
> > +		update = true;
> > +	}
> >  
> > +	if (update)
> >  		LOG(RkISP1Awb, Debug)
> >  			<< "Set colour gains to " << awb.gains.manual;
> > -	}
> >  
> > -	frameContext.awb.autoEnabled = awb.autoEnabled;
> > -
> > -	if (!awb.autoEnabled)
> > -		frameContext.awb.gains = awb.gains.manual;
> > +	frameContext.awb.gains = awb.gains.manual;
> > +	frameContext.awb.temperatureK = awb.temperatureK;
> >  }
> >  
> >  /**
> > @@ -126,8 +154,10 @@ void Awb::prepare(IPAContext &context, const uint32_t frame,
> >  	 * This is the latest time we can read the active state. This is the
> >  	 * most up-to-date automatic values we can read.
> >  	 */
> > -	if (frameContext.awb.autoEnabled)
> > +	if (frameContext.awb.autoEnabled) {
> >  		frameContext.awb.gains = context.activeState.awb.gains.automatic;
> > +		frameContext.awb.temperatureK = context.activeState.awb.temperatureK;
> > +	}
> >  
> >  	auto gainConfig = params->block<BlockType::AwbGain>();
> >  	gainConfig.setEnabled(true);
> > @@ -206,7 +236,7 @@ void Awb::process(IPAContext &context,
> >  			static_cast<float>(frameContext.awb.gains.r()),
> >  			static_cast<float>(frameContext.awb.gains.b())
> >  		});
> > -	metadata.set(controls::ColourTemperature, activeState.awb.temperatureK);
> > +	metadata.set(controls::ColourTemperature, frameContext.awb.temperatureK);
> >  
> >  	if (!stats || !(stats->meas_type & RKISP1_CIF_ISP_STAT_AWB)) {
> >  		LOG(RkISP1Awb, Error) << "AWB data is missing in statistics";
> > @@ -281,9 +311,6 @@ void Awb::process(IPAContext &context,
> >  
> >  	activeState.awb.temperatureK = estimateCCT(rgbMeans);
> >  
> > -	/* Metadata shall contain the up to date measurement */
> > -	metadata.set(controls::ColourTemperature, activeState.awb.temperatureK);
> > -
> >  	/*
> >  	 * Estimate the red and blue gains to apply in a grey world. The green
> >  	 * gain is hardcoded to 1.0. Avoid divisions by zero by clamping the
> > diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
> > index deb8c196f1b8..4b50015beee8 100644
> > --- a/src/ipa/rkisp1/ipa_context.h
> > +++ b/src/ipa/rkisp1/ipa_context.h
> > @@ -135,6 +135,7 @@ struct IPAFrameContext : public FrameContext {
> >  	struct {
> >  		RGB<double> gains;
> >  		bool autoEnabled;
> > +		unsigned int temperatureK;
> >  	} awb;
> >  
> >  	struct {
> 
> -- 
> Regards,
> 
> Laurent Pinchart
Laurent Pinchart Dec. 20, 2024, 10:16 a.m. UTC | #3
On Fri, Dec 20, 2024 at 11:07:14AM +0100, Stefan Klug wrote:
> Hi Laurent,
> 
> Thank you for the review. 
> 
> On Fri, Dec 20, 2024 at 11:54:57AM +0200, Laurent Pinchart wrote:
> > Hi Stefan,
> > 
> > Thank you for the patch.
> > 
> > On Thu, Dec 19, 2024 at 06:57:20PM +0100, Stefan Klug wrote:
> > > There are many use-cases (tuning-validation, working in static
> > > environments) where a manual ColourTemperature control is helpful.
> > > Implement that by interpolating and applying the white balance gains
> > > from the tuning file according to the requested colour temperature. If
> > > colour gains are provided on the same request, they take precedence.
> > > Store the colour temperature used for a given frame in the frame context
> > > and report that in metadata.
> > > 
> > > Note that in the automatic case, the colour gains are still based on the
> > > gray world model and the CT curve from the tuning file get ignored.
> > > 
> > > Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
> > > Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
> > > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> > > 
> > > ---
> > > 
> > > Changes in v6:
> > > - Updated commit message
> > > - Moved retrieval of controls to the place where needed
> > > - Output the colour temperature applied to a frame in metadata
> > > ---
> > >  src/ipa/rkisp1/algorithms/awb.cpp | 51 +++++++++++++++++++++++--------
> > >  src/ipa/rkisp1/ipa_context.h      |  1 +
> > >  2 files changed, 40 insertions(+), 12 deletions(-)
> > > 
> > > diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp
> > > index e23f67a96edf..cffaa06a22c1 100644
> > > --- a/src/ipa/rkisp1/algorithms/awb.cpp
> > > +++ b/src/ipa/rkisp1/algorithms/awb.cpp
> > > @@ -33,6 +33,10 @@ namespace ipa::rkisp1::algorithms {
> > >  
> > >  LOG_DEFINE_CATEGORY(RkISP1Awb)
> > >  
> > > +constexpr int32_t kMinColourTemperature = 2500;
> > > +constexpr int32_t kMaxColourTemperature = 10000;
> > > +constexpr int32_t kDefaultColourTemperature = 5000;
> > > +
> > >  /* Minimum mean value below which AWB can't operate. */
> > >  constexpr double kMeanMinThreshold = 2.0;
> > >  
> > > @@ -44,8 +48,13 @@ Awb::Awb()
> > >  /**
> > >   * \copydoc libcamera::ipa::Algorithm::init
> > >   */
> > > -int Awb::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData)
> > > +int Awb::init(IPAContext &context, const YamlObject &tuningData)
> > >  {
> > > +	auto &cmap = context.ctrlMap;
> > > +	cmap[&controls::ColourTemperature] = ControlInfo(kMinColourTemperature,
> > > +							 kMaxColourTemperature,
> > > +							 kDefaultColourTemperature);
> > > +
> > >  	Interpolator<Vector<double, 2>> gainCurve;
> > >  	int ret = gainCurve.readYaml(tuningData["colourGains"], "ct", "gains");
> > >  	if (ret < 0)
> > > @@ -68,6 +77,7 @@ int Awb::configure(IPAContext &context,
> > >  	context.activeState.awb.gains.manual = RGB<double>{ 1.0 };
> > >  	context.activeState.awb.gains.automatic = RGB<double>{ 1.0 };
> > >  	context.activeState.awb.autoEnabled = true;
> > > +	context.activeState.awb.temperatureK = kDefaultColourTemperature;
> > >  
> > >  	/*
> > >  	 * Define the measurement window for AWB as a centered rectangle
> > > @@ -101,19 +111,37 @@ void Awb::queueRequest(IPAContext &context,
> > >  			<< (*awbEnable ? "Enabling" : "Disabling") << " AWB";
> > >  	}
> > >  
> > > +	frameContext.awb.autoEnabled = awb.autoEnabled;
> > > +
> > > +	if (awb.autoEnabled)
> > > +		return;
> > > +
> > >  	const auto &colourGains = controls.get(controls::ColourGains);
> > > -	if (colourGains && !awb.autoEnabled) {
> > > +	const auto &colourTemperature = controls.get(controls::ColourTemperature);
> > > +	bool update = false;
> > > +	if (colourGains) {
> > >  		awb.gains.manual.r() = (*colourGains)[0];
> > >  		awb.gains.manual.b() = (*colourGains)[1];
> > > +		/*
> > > +		 * \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.
> > > +		 */
> > 
> > Will we require all cameras to implement bayesian AWB ? If not, the the
> > controls documentation need to allow that. I suppose that
> > ColourTemperature will then not be reported as a settable control by the
> > camera, so application will know.
> 
> This case happens when setting the colour gains. So making the
> ColourTemperature an output only won't help here. We could stop
> reporting it in metadata. But that is for later.

What I meant is that, it CT is output only, we could document that it
doesn't get computed from gains (and likely also that it doesn't get
reported in embedded data in manual mode).

> > I'm fine clarifying the documentation on top of this series. Can you
> > make sure it gets done ?
> > 
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
> Thanks!
> 
> > > +		update = true;
> > > +	} else if (colourTemperature && colourGainCurve_) {
> > > +		const auto &gains = colourGainCurve_->getInterpolated(*colourTemperature);
> > > +		awb.gains.manual.r() = gains[0];
> > > +		awb.gains.manual.b() = gains[1];
> > > +		awb.temperatureK = *colourTemperature;
> > > +		update = true;
> > > +	}
> > >  
> > > +	if (update)
> > >  		LOG(RkISP1Awb, Debug)
> > >  			<< "Set colour gains to " << awb.gains.manual;
> > > -	}
> > >  
> > > -	frameContext.awb.autoEnabled = awb.autoEnabled;
> > > -
> > > -	if (!awb.autoEnabled)
> > > -		frameContext.awb.gains = awb.gains.manual;
> > > +	frameContext.awb.gains = awb.gains.manual;
> > > +	frameContext.awb.temperatureK = awb.temperatureK;
> > >  }
> > >  
> > >  /**
> > > @@ -126,8 +154,10 @@ void Awb::prepare(IPAContext &context, const uint32_t frame,
> > >  	 * This is the latest time we can read the active state. This is the
> > >  	 * most up-to-date automatic values we can read.
> > >  	 */
> > > -	if (frameContext.awb.autoEnabled)
> > > +	if (frameContext.awb.autoEnabled) {
> > >  		frameContext.awb.gains = context.activeState.awb.gains.automatic;
> > > +		frameContext.awb.temperatureK = context.activeState.awb.temperatureK;
> > > +	}
> > >  
> > >  	auto gainConfig = params->block<BlockType::AwbGain>();
> > >  	gainConfig.setEnabled(true);
> > > @@ -206,7 +236,7 @@ void Awb::process(IPAContext &context,
> > >  			static_cast<float>(frameContext.awb.gains.r()),
> > >  			static_cast<float>(frameContext.awb.gains.b())
> > >  		});
> > > -	metadata.set(controls::ColourTemperature, activeState.awb.temperatureK);
> > > +	metadata.set(controls::ColourTemperature, frameContext.awb.temperatureK);
> > >  
> > >  	if (!stats || !(stats->meas_type & RKISP1_CIF_ISP_STAT_AWB)) {
> > >  		LOG(RkISP1Awb, Error) << "AWB data is missing in statistics";
> > > @@ -281,9 +311,6 @@ void Awb::process(IPAContext &context,
> > >  
> > >  	activeState.awb.temperatureK = estimateCCT(rgbMeans);
> > >  
> > > -	/* Metadata shall contain the up to date measurement */
> > > -	metadata.set(controls::ColourTemperature, activeState.awb.temperatureK);
> > > -
> > >  	/*
> > >  	 * Estimate the red and blue gains to apply in a grey world. The green
> > >  	 * gain is hardcoded to 1.0. Avoid divisions by zero by clamping the
> > > diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
> > > index deb8c196f1b8..4b50015beee8 100644
> > > --- a/src/ipa/rkisp1/ipa_context.h
> > > +++ b/src/ipa/rkisp1/ipa_context.h
> > > @@ -135,6 +135,7 @@ struct IPAFrameContext : public FrameContext {
> > >  	struct {
> > >  		RGB<double> gains;
> > >  		bool autoEnabled;
> > > +		unsigned int temperatureK;
> > >  	} awb;
> > >  
> > >  	struct {

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp
index e23f67a96edf..cffaa06a22c1 100644
--- a/src/ipa/rkisp1/algorithms/awb.cpp
+++ b/src/ipa/rkisp1/algorithms/awb.cpp
@@ -33,6 +33,10 @@  namespace ipa::rkisp1::algorithms {
 
 LOG_DEFINE_CATEGORY(RkISP1Awb)
 
+constexpr int32_t kMinColourTemperature = 2500;
+constexpr int32_t kMaxColourTemperature = 10000;
+constexpr int32_t kDefaultColourTemperature = 5000;
+
 /* Minimum mean value below which AWB can't operate. */
 constexpr double kMeanMinThreshold = 2.0;
 
@@ -44,8 +48,13 @@  Awb::Awb()
 /**
  * \copydoc libcamera::ipa::Algorithm::init
  */
-int Awb::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData)
+int Awb::init(IPAContext &context, const YamlObject &tuningData)
 {
+	auto &cmap = context.ctrlMap;
+	cmap[&controls::ColourTemperature] = ControlInfo(kMinColourTemperature,
+							 kMaxColourTemperature,
+							 kDefaultColourTemperature);
+
 	Interpolator<Vector<double, 2>> gainCurve;
 	int ret = gainCurve.readYaml(tuningData["colourGains"], "ct", "gains");
 	if (ret < 0)
@@ -68,6 +77,7 @@  int Awb::configure(IPAContext &context,
 	context.activeState.awb.gains.manual = RGB<double>{ 1.0 };
 	context.activeState.awb.gains.automatic = RGB<double>{ 1.0 };
 	context.activeState.awb.autoEnabled = true;
+	context.activeState.awb.temperatureK = kDefaultColourTemperature;
 
 	/*
 	 * Define the measurement window for AWB as a centered rectangle
@@ -101,19 +111,37 @@  void Awb::queueRequest(IPAContext &context,
 			<< (*awbEnable ? "Enabling" : "Disabling") << " AWB";
 	}
 
+	frameContext.awb.autoEnabled = awb.autoEnabled;
+
+	if (awb.autoEnabled)
+		return;
+
 	const auto &colourGains = controls.get(controls::ColourGains);
-	if (colourGains && !awb.autoEnabled) {
+	const auto &colourTemperature = controls.get(controls::ColourTemperature);
+	bool update = false;
+	if (colourGains) {
 		awb.gains.manual.r() = (*colourGains)[0];
 		awb.gains.manual.b() = (*colourGains)[1];
+		/*
+		 * \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.
+		 */
+		update = true;
+	} else if (colourTemperature && colourGainCurve_) {
+		const auto &gains = colourGainCurve_->getInterpolated(*colourTemperature);
+		awb.gains.manual.r() = gains[0];
+		awb.gains.manual.b() = gains[1];
+		awb.temperatureK = *colourTemperature;
+		update = true;
+	}
 
+	if (update)
 		LOG(RkISP1Awb, Debug)
 			<< "Set colour gains to " << awb.gains.manual;
-	}
 
-	frameContext.awb.autoEnabled = awb.autoEnabled;
-
-	if (!awb.autoEnabled)
-		frameContext.awb.gains = awb.gains.manual;
+	frameContext.awb.gains = awb.gains.manual;
+	frameContext.awb.temperatureK = awb.temperatureK;
 }
 
 /**
@@ -126,8 +154,10 @@  void Awb::prepare(IPAContext &context, const uint32_t frame,
 	 * This is the latest time we can read the active state. This is the
 	 * most up-to-date automatic values we can read.
 	 */
-	if (frameContext.awb.autoEnabled)
+	if (frameContext.awb.autoEnabled) {
 		frameContext.awb.gains = context.activeState.awb.gains.automatic;
+		frameContext.awb.temperatureK = context.activeState.awb.temperatureK;
+	}
 
 	auto gainConfig = params->block<BlockType::AwbGain>();
 	gainConfig.setEnabled(true);
@@ -206,7 +236,7 @@  void Awb::process(IPAContext &context,
 			static_cast<float>(frameContext.awb.gains.r()),
 			static_cast<float>(frameContext.awb.gains.b())
 		});
-	metadata.set(controls::ColourTemperature, activeState.awb.temperatureK);
+	metadata.set(controls::ColourTemperature, frameContext.awb.temperatureK);
 
 	if (!stats || !(stats->meas_type & RKISP1_CIF_ISP_STAT_AWB)) {
 		LOG(RkISP1Awb, Error) << "AWB data is missing in statistics";
@@ -281,9 +311,6 @@  void Awb::process(IPAContext &context,
 
 	activeState.awb.temperatureK = estimateCCT(rgbMeans);
 
-	/* Metadata shall contain the up to date measurement */
-	metadata.set(controls::ColourTemperature, activeState.awb.temperatureK);
-
 	/*
 	 * Estimate the red and blue gains to apply in a grey world. The green
 	 * gain is hardcoded to 1.0. Avoid divisions by zero by clamping the
diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
index deb8c196f1b8..4b50015beee8 100644
--- a/src/ipa/rkisp1/ipa_context.h
+++ b/src/ipa/rkisp1/ipa_context.h
@@ -135,6 +135,7 @@  struct IPAFrameContext : public FrameContext {
 	struct {
 		RGB<double> gains;
 		bool autoEnabled;
+		unsigned int temperatureK;
 	} awb;
 
 	struct {