[libcamera-devel,04/10] libcamera: ipa: raspberrypi: agc: Improve centre-weighted luminance calucation
diff mbox series

Message ID 20201116164918.2055-5-david.plowman@raspberrypi.com
State Superseded
Headers show
Series
  • Raspberry Pi AGC
Related show

Commit Message

David Plowman Nov. 16, 2020, 4:49 p.m. UTC
Previously the calculation computed Y for each region before returning
the weighted average, which "baked in" the over-importance of small
statistics regions. The revised calculation will treat all pixels
equally when the region weights are the same, making it easier to
use. With the previous scheme, proper "average" metering was difficult
to implement.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
---
 src/ipa/raspberrypi/controller/rpi/agc.cpp | 25 +++++++++++++---------
 1 file changed, 15 insertions(+), 10 deletions(-)

Comments

Naushir Patuck Nov. 17, 2020, 10:40 a.m. UTC | #1
Hi David,


On Mon, 16 Nov 2020 at 16:49, David Plowman <david.plowman@raspberrypi.com>
wrote:

> Previously the calculation computed Y for each region before returning
> the weighted average, which "baked in" the over-importance of small
> statistics regions. The revised calculation will treat all pixels
> equally when the region weights are the same, making it easier to
> use. With the previous scheme, proper "average" metering was difficult
> to implement.
>
> Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
>

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


> ---
>  src/ipa/raspberrypi/controller/rpi/agc.cpp | 25 +++++++++++++---------
>  1 file changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp
> b/src/ipa/raspberrypi/controller/rpi/agc.cpp
> index d29b1156..ead28398 100644
> --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
> +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
> @@ -386,18 +386,23 @@ static double compute_initial_Y(bcm2835_isp_stats
> *stats, Metadata *image_metada
>         awb.gain_r = awb.gain_g = awb.gain_b = 1.0; // in case no metadata
>         if (image_metadata->Get("awb.status", awb) != 0)
>                 LOG(RPiAgc, Warning) << "Agc: no AWB status found";
> -       double Y_sum = 0, weight_sum = 0;
> +       // Note how the calculation below means that equal weights give you
> +       // "average" metering (i.e. all pixels equally important).
> +       double R_sum = 0, G_sum = 0, B_sum = 0, pixel_sum = 0;
>         for (int i = 0; i < AGC_STATS_SIZE; i++) {
> -               if (regions[i].counted == 0)
> -                       continue;
> -               weight_sum += weights[i];
> -               double Y = regions[i].r_sum * awb.gain_r * .299 +
> -                          regions[i].g_sum * awb.gain_g * .587 +
> -                          regions[i].b_sum * awb.gain_b * .114;
> -               Y /= regions[i].counted;
> -               Y_sum += Y * weights[i];
> +               R_sum += regions[i].r_sum * weights[i];
> +               G_sum += regions[i].g_sum * weights[i];
> +               B_sum += regions[i].b_sum * weights[i];
> +               pixel_sum += regions[i].counted * weights[i];
>         }
> -       return Y_sum / weight_sum / (1 << PIPELINE_BITS);
> +       if (pixel_sum == 0.0) {
> +               LOG(RPiAgc, Warning) << "compute_initial_Y: pixel_sum is
> zero";
> +               return 0;
> +       }
> +       double Y_sum = R_sum * awb.gain_r * .299 +
> +                      G_sum * awb.gain_g * .587 +
> +                      B_sum * awb.gain_b * .114;
> +       return Y_sum / pixel_sum / (1 << PIPELINE_BITS);
>  }
>
>  // We handle extra gain through EV by adjusting our Y targets. However,
> you
> --
> 2.20.1
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel@lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
>

Patch
diff mbox series

diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp
index d29b1156..ead28398 100644
--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
@@ -386,18 +386,23 @@  static double compute_initial_Y(bcm2835_isp_stats *stats, Metadata *image_metada
 	awb.gain_r = awb.gain_g = awb.gain_b = 1.0; // in case no metadata
 	if (image_metadata->Get("awb.status", awb) != 0)
 		LOG(RPiAgc, Warning) << "Agc: no AWB status found";
-	double Y_sum = 0, weight_sum = 0;
+	// Note how the calculation below means that equal weights give you
+	// "average" metering (i.e. all pixels equally important).
+	double R_sum = 0, G_sum = 0, B_sum = 0, pixel_sum = 0;
 	for (int i = 0; i < AGC_STATS_SIZE; i++) {
-		if (regions[i].counted == 0)
-			continue;
-		weight_sum += weights[i];
-		double Y = regions[i].r_sum * awb.gain_r * .299 +
-			   regions[i].g_sum * awb.gain_g * .587 +
-			   regions[i].b_sum * awb.gain_b * .114;
-		Y /= regions[i].counted;
-		Y_sum += Y * weights[i];
+		R_sum += regions[i].r_sum * weights[i];
+		G_sum += regions[i].g_sum * weights[i];
+		B_sum += regions[i].b_sum * weights[i];
+		pixel_sum += regions[i].counted * weights[i];
 	}
-	return Y_sum / weight_sum / (1 << PIPELINE_BITS);
+	if (pixel_sum == 0.0) {
+		LOG(RPiAgc, Warning) << "compute_initial_Y: pixel_sum is zero";
+		return 0;
+	}
+	double Y_sum = R_sum * awb.gain_r * .299 +
+		       G_sum * awb.gain_g * .587 +
+		       B_sum * awb.gain_b * .114;
+	return Y_sum / pixel_sum / (1 << PIPELINE_BITS);
 }
 
 // We handle extra gain through EV by adjusting our Y targets. However, you