[libcamera-devel] [PATCH 09/10] libcamera: src: ipa: raspberrypi: agc: Improve gain update calculation for partly saturated images
Naushir Patuck
naush at raspberrypi.com
Tue Nov 17 12:12:35 CET 2020
Hi David,
On Mon, 16 Nov 2020 at 16:49, David Plowman <david.plowman at raspberrypi.com>
wrote:
> When parts of an image saturate then the image brightness no longer
> increases linearly with increased exposure/gain. Having calculated a
> linear gain value it's better then to try it, allowing for saturating
> regions, and if necessary increase the gain some more. We repeat this
> several times.
>
> Signed-off-by: David Plowman <david.plowman at raspberrypi.com>
>
Reviewed-by: Naushir Patuck <naush at raspberrypi.com>
> ---
> src/ipa/raspberrypi/controller/rpi/agc.cpp | 34 +++++++++++++++-------
> 1 file changed, 24 insertions(+), 10 deletions(-)
>
> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp
> b/src/ipa/raspberrypi/controller/rpi/agc.cpp
> index 1037f968..93b46a28 100644
> --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
> +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
> @@ -422,17 +422,21 @@ void Agc::fetchAwbStatus(Metadata *image_metadata)
> }
>
> static double compute_initial_Y(bcm2835_isp_stats *stats, AwbStatus const
> &awb,
> - double weights[])
> + double weights[], double gain)
> {
> bcm2835_isp_stats_region *regions = stats->agc_stats;
> // 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++) {
> - 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];
> + double counted = regions[i].counted;
> + double r_sum = std::min(regions[i].r_sum * gain, ((1 <<
> PIPELINE_BITS) - 1) * counted);
> + double g_sum = std::min(regions[i].g_sum * gain, ((1 <<
> PIPELINE_BITS) - 1) * counted);
> + double b_sum = std::min(regions[i].b_sum * gain, ((1 <<
> PIPELINE_BITS) - 1) * counted);
> + R_sum += r_sum * weights[i];
> + G_sum += g_sum * weights[i];
> + B_sum += b_sum * weights[i];
> + pixel_sum += counted * weights[i];
> }
> if (pixel_sum == 0.0) {
> LOG(RPiAgc, Warning) << "compute_initial_Y: pixel_sum is
> zero";
> @@ -476,11 +480,21 @@ void Agc::computeGain(bcm2835_isp_stats *statistics,
> Metadata *image_metadata,
> target_Y =
>
> config_.Y_target.Eval(config_.Y_target.Domain().Clip(lux.lux));
> target_Y = std::min(EV_GAIN_Y_TARGET_LIMIT, target_Y * ev_gain);
> - double initial_Y = compute_initial_Y(statistics, awb_,
> - metering_mode_->weights);
> - gain = std::min(10.0, target_Y / (initial_Y + .001));
> - LOG(RPiAgc, Debug) << "Initially Y " << initial_Y << " target " <<
> target_Y
> - << " gives gain " << gain;
> +
> + // Do this calculation a few times as brightness increase can be
> + // non-linear when there are saturated regions.
> + gain = 1.0;
> + for (int i = 0; i < 8; i++) {
> + double initial_Y = compute_initial_Y(statistics, awb_,
> +
> metering_mode_->weights, gain);
> + double extra_gain = std::min(10.0, target_Y / (initial_Y +
> .001));
> + gain *= extra_gain;
> + LOG(RPiAgc, Debug) << "Initial Y " << initial_Y << "
> target " << target_Y
> + << " gives gain " << gain;
> + if (extra_gain < 1.01) // close enough
> + break;
> + }
> +
> for (auto &c : *constraint_mode_) {
> double new_target_Y;
> double new_gain =
> --
> 2.20.1
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20201117/d244aca2/attachment.htm>
More information about the libcamera-devel
mailing list