Message ID | 20201116164918.2055-10-david.plowman@raspberrypi.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hi David, On Mon, 16 Nov 2020 at 16:49, David Plowman <david.plowman@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@raspberrypi.com> > Reviewed-by: Naushir Patuck <naush@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@lists.libcamera.org > https://lists.libcamera.org/listinfo/libcamera-devel >
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 =
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@raspberrypi.com> --- src/ipa/raspberrypi/controller/rpi/agc.cpp | 34 +++++++++++++++------- 1 file changed, 24 insertions(+), 10 deletions(-)