[5/5] ipa: rpi: lux: Use floating statistics region to obtain the current Y value
diff mbox series

Message ID 20251017102704.3887-6-david.plowman@raspberrypi.com
State Accepted
Headers show
Series
  • Fix and improve full image Y statistics
Related show

Commit Message

David Plowman Oct. 17, 2025, 10:05 a.m. UTC
The Y value from the first floating region is now a better choice for
a Y value that is invariant to (for example) the metering mode.

Both VC4 and PiSP platforms store full image Y statistics here.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
---
 src/ipa/rpi/controller/rpi/lux.cpp | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

Comments

Stefan Klug Oct. 20, 2025, 10:13 a.m. UTC | #1
Hi David,

Quoting David Plowman (2025-10-17 12:05:41)
> The Y value from the first floating region is now a better choice for
> a Y value that is invariant to (for example) the metering mode.
> 
> Both VC4 and PiSP platforms store full image Y statistics here.
> 
> Signed-off-by: David Plowman <david.plowman@raspberrypi.com>

Looks good to me.

Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>

Cheers,
Stefan

> ---
>  src/ipa/rpi/controller/rpi/lux.cpp | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/src/ipa/rpi/controller/rpi/lux.cpp b/src/ipa/rpi/controller/rpi/lux.cpp
> index acaa6e57..7dab27cc 100644
> --- a/src/ipa/rpi/controller/rpi/lux.cpp
> +++ b/src/ipa/rpi/controller/rpi/lux.cpp
> @@ -85,14 +85,21 @@ void Lux::process(StatisticsPtr &stats, Metadata *imageMetadata)
>  {
>         DeviceStatus deviceStatus;
>         if (imageMetadata->get("device.status", deviceStatus) == 0) {
> +               /*
> +                * We've set up the first floating AGC region to collect full image stats. This
> +                * is a better choice than the Y-histogram, for example, because it's invariant
> +                * to the metering mode (and cheaper to evaluate).
> +                */
> +               auto const &fullImageStats = stats->agcRegions.getFloating(0);
> +               double currentY = static_cast<double>(fullImageStats.val.ySum) / fullImageStats.counted;
> +
>                 double currentGain = deviceStatus.analogueGain;
>                 double currentAperture = deviceStatus.aperture.value_or(currentAperture_);
> -               double currentY = stats->yHist.interQuantileMean(0, 1);
>                 double gainRatio = referenceGain_ / currentGain;
>                 double exposureTimeRatio =
>                         referenceExposureTime_ / deviceStatus.exposureTime;
>                 double apertureRatio = referenceAperture_ / currentAperture;
> -               double yRatio = currentY * (65536 / stats->yHist.bins()) / referenceY_;
> +               double yRatio = currentY / referenceY_;
>                 double estimatedLux = exposureTimeRatio * gainRatio *
>                                       apertureRatio * apertureRatio *
>                                       yRatio * referenceLux_ / sensitivity_;
> -- 
> 2.47.3
>
Naushir Patuck Oct. 23, 2025, 7:40 a.m. UTC | #2
Hi David,


On Fri, 17 Oct 2025 at 11:27, David Plowman <david.plowman@raspberrypi.com>
wrote:

> The Y value from the first floating region is now a better choice for
> a Y value that is invariant to (for example) the metering mode.
>
> Both VC4 and PiSP platforms store full image Y statistics here.
>
> Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
>

Reviewed-by: Naushir Patuck <naush@raspberrypi.com>


> ---
>  src/ipa/rpi/controller/rpi/lux.cpp | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/src/ipa/rpi/controller/rpi/lux.cpp
> b/src/ipa/rpi/controller/rpi/lux.cpp
> index acaa6e57..7dab27cc 100644
> --- a/src/ipa/rpi/controller/rpi/lux.cpp
> +++ b/src/ipa/rpi/controller/rpi/lux.cpp
> @@ -85,14 +85,21 @@ void Lux::process(StatisticsPtr &stats, Metadata
> *imageMetadata)
>  {
>         DeviceStatus deviceStatus;
>         if (imageMetadata->get("device.status", deviceStatus) == 0) {
> +               /*
> +                * We've set up the first floating AGC region to collect
> full image stats. This
> +                * is a better choice than the Y-histogram, for example,
> because it's invariant
> +                * to the metering mode (and cheaper to evaluate).
> +                */
> +               auto const &fullImageStats =
> stats->agcRegions.getFloating(0);
> +               double currentY =
> static_cast<double>(fullImageStats.val.ySum) / fullImageStats.counted;
> +
>                 double currentGain = deviceStatus.analogueGain;
>                 double currentAperture =
> deviceStatus.aperture.value_or(currentAperture_);
> -               double currentY = stats->yHist.interQuantileMean(0, 1);
>                 double gainRatio = referenceGain_ / currentGain;
>                 double exposureTimeRatio =
>                         referenceExposureTime_ / deviceStatus.exposureTime;
>                 double apertureRatio = referenceAperture_ /
> currentAperture;
> -               double yRatio = currentY * (65536 / stats->yHist.bins()) /
> referenceY_;
> +               double yRatio = currentY / referenceY_;
>                 double estimatedLux = exposureTimeRatio * gainRatio *
>                                       apertureRatio * apertureRatio *
>                                       yRatio * referenceLux_ /
> sensitivity_;
> --
> 2.47.3
>
>

Patch
diff mbox series

diff --git a/src/ipa/rpi/controller/rpi/lux.cpp b/src/ipa/rpi/controller/rpi/lux.cpp
index acaa6e57..7dab27cc 100644
--- a/src/ipa/rpi/controller/rpi/lux.cpp
+++ b/src/ipa/rpi/controller/rpi/lux.cpp
@@ -85,14 +85,21 @@  void Lux::process(StatisticsPtr &stats, Metadata *imageMetadata)
 {
 	DeviceStatus deviceStatus;
 	if (imageMetadata->get("device.status", deviceStatus) == 0) {
+		/*
+		 * We've set up the first floating AGC region to collect full image stats. This
+		 * is a better choice than the Y-histogram, for example, because it's invariant
+		 * to the metering mode (and cheaper to evaluate).
+		 */
+		auto const &fullImageStats = stats->agcRegions.getFloating(0);
+		double currentY = static_cast<double>(fullImageStats.val.ySum) / fullImageStats.counted;
+
 		double currentGain = deviceStatus.analogueGain;
 		double currentAperture = deviceStatus.aperture.value_or(currentAperture_);
-		double currentY = stats->yHist.interQuantileMean(0, 1);
 		double gainRatio = referenceGain_ / currentGain;
 		double exposureTimeRatio =
 			referenceExposureTime_ / deviceStatus.exposureTime;
 		double apertureRatio = referenceAperture_ / currentAperture;
-		double yRatio = currentY * (65536 / stats->yHist.bins()) / referenceY_;
+		double yRatio = currentY / referenceY_;
 		double estimatedLux = exposureTimeRatio * gainRatio *
 				      apertureRatio * apertureRatio *
 				      yRatio * referenceLux_ / sensitivity_;