From 9db94a3635b8cc0963fdbc8e33c07890ce177359 Mon Sep 17 00:00:00 2001 From: David Plowman 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 Reviewed-by: Naushir Patuck Acked-by: Kieran Bingham Signed-off-by: Kieran Bingham --- src/ipa/raspberrypi/controller/rpi/agc.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'src/ipa/raspberrypi') 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