From 9db94a3635b8cc0963fdbc8e33c07890ce177359 Mon Sep 17 00:00:00 2001
From: David Plowman <david.plowman@raspberrypi.com>
Date: Mon, 23 Nov 2020 07:37:58 +0000
Subject: libcamera: ipa: raspberrypi: agc: Improve centre-weighted luminance
 calucation

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>
Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 src/ipa/raspberrypi/controller/rpi/agc.cpp | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

(limited to 'src/ipa')

diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp
index 9a5d84f7..f0c70a0a 100644
--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
@@ -385,18 +385,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
-- 
cgit v1.2.1