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

Message ID 20201123073804.3125-5-david.plowman@raspberrypi.com
State Accepted
Commit 9db94a3635b8cc0963fdbc8e33c07890ce177359
Headers show
Series
  • Raspberry Pi AGC
Related show

Commit Message

David Plowman Nov. 23, 2020, 7:37 a.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>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
---
 src/ipa/raspberrypi/controller/rpi/agc.cpp | 25 +++++++++++++---------
 1 file changed, 15 insertions(+), 10 deletions(-)

Patch
diff mbox series

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