ipa: ipu3: agc: Return the inter-quantile mean from measureBrightness()

The inter-quantile mean is a value that is computed as part of the AGC
run. It doesn't need to be stored in a member variable. Return it from
measureBrightness(), which makes the flow of data easier to follow.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
Laurent Pinchart 2021-11-16 16:29:23 +02:00
parent 6e02f67457
commit a2b4975a1c
2 changed files with 33 additions and 29 deletions

View file

@ -70,7 +70,7 @@ static constexpr uint32_t kNumStartupFrames = 10;
static constexpr double kRelativeLuminanceTarget = 0.16; static constexpr double kRelativeLuminanceTarget = 0.16;
Agc::Agc() Agc::Agc()
: frameCount_(0), iqMean_(0.0), lineDuration_(0s), minShutterSpeed_(0s), : frameCount_(0), lineDuration_(0s), minShutterSpeed_(0s),
maxShutterSpeed_(0s), filteredExposure_(0s), currentExposure_(0s) maxShutterSpeed_(0s), filteredExposure_(0s), currentExposure_(0s)
{ {
} }
@ -108,9 +108,10 @@ int Agc::configure(IPAContext &context, const IPAConfigInfo &configInfo)
* \brief Estimate the mean value of the top 2% of the histogram * \brief Estimate the mean value of the top 2% of the histogram
* \param[in] stats The statistics computed by the ImgU * \param[in] stats The statistics computed by the ImgU
* \param[in] grid The grid used to store the statistics in the IPU3 * \param[in] grid The grid used to store the statistics in the IPU3
* \return The mean value of the top 2% of the histogram
*/ */
void Agc::measureBrightness(const ipu3_uapi_stats_3a *stats, double Agc::measureBrightness(const ipu3_uapi_stats_3a *stats,
const ipu3_uapi_grid_config &grid) const ipu3_uapi_grid_config &grid) const
{ {
/* Initialise the histogram array */ /* Initialise the histogram array */
uint32_t hist[knumHistogramBins] = { 0 }; uint32_t hist[knumHistogramBins] = { 0 };
@ -135,8 +136,8 @@ void Agc::measureBrightness(const ipu3_uapi_stats_3a *stats,
} }
} }
/* Estimate the quantile mean of the top 2% of the histogram */ /* Estimate the quantile mean of the top 2% of the histogram. */
iqMean_ = Histogram(Span<uint32_t>(hist)).interQuantileMean(0.98, 1.0); return Histogram(Span<uint32_t>(hist)).interQuantileMean(0.98, 1.0);
} }
/** /**
@ -174,28 +175,22 @@ void Agc::filterExposure()
* \brief Estimate the new exposure and gain values * \brief Estimate the new exposure and gain values
* \param[inout] frameContext The shared IPA frame Context * \param[inout] frameContext The shared IPA frame Context
* \param[in] yGain The gain calculated based on the relative luminance target * \param[in] yGain The gain calculated based on the relative luminance target
* \param[in] iqMeanGain The gain calculated based on the relative luminance target
*/ */
void Agc::computeExposure(IPAFrameContext &frameContext, double yGain) void Agc::computeExposure(IPAFrameContext &frameContext, double yGain,
double iqMeanGain)
{ {
/* Get the effective exposure and gain applied on the sensor. */ /* Get the effective exposure and gain applied on the sensor. */
uint32_t exposure = frameContext.sensor.exposure; uint32_t exposure = frameContext.sensor.exposure;
double analogueGain = frameContext.sensor.gain; double analogueGain = frameContext.sensor.gain;
/* /* Use the highest of the two gain estimates. */
* Estimate the gain needed to have the proportion of pixels in a given double evGain = std::max(yGain, iqMeanGain);
* desired range. iqMean_ returns the mean value of the top 2% of the
* cumulative histogram, and we want it to be as close as possible to a
* configured target.
*/
double evGain = kEvGainTarget * knumHistogramBins / iqMean_;
if (evGain < yGain)
evGain = yGain;
/* Consider within 1% of the target as correctly exposed */ /* Consider within 1% of the target as correctly exposed */
if (std::abs(evGain - 1.0) < 0.01) if (std::abs(evGain - 1.0) < 0.01)
LOG(IPU3Agc, Debug) << "We are well exposed (iqMean = " LOG(IPU3Agc, Debug) << "We are well exposed (evGain = "
<< iqMean_ << ")"; << evGain << ")";
/* extracted from Rpi::Agc::computeTargetExposure */ /* extracted from Rpi::Agc::computeTargetExposure */
@ -308,15 +303,25 @@ double Agc::estimateLuminance(IPAFrameContext &frameContext,
*/ */
void Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats) void Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats)
{ {
measureBrightness(stats, context.configuration.grid.bdsGrid); /*
* Estimate the gain needed to have the proportion of pixels in a given
* desired range. iqMean is the mean value of the top 2% of the
* cumulative histogram, and we want it to be as close as possible to a
* configured target.
*/
double iqMean = measureBrightness(stats, context.configuration.grid.bdsGrid);
double iqMeanGain = kEvGainTarget * knumHistogramBins / iqMean;
/*
* Estimate the gain needed to achieve a relative luminance target. To
* account for non-linearity caused by saturation, the value needs to be
* estimated in an iterative process, as multiplying by a gain will not
* increase the relative luminance by the same factor if some image
* regions are saturated.
*/
double yGain = 1.0; double yGain = 1.0;
double yTarget = kRelativeLuminanceTarget; double yTarget = kRelativeLuminanceTarget;
/*
* Do this calculation a few times as brightness increase can be
* non-linear when there are saturated regions.
*/
for (unsigned int i = 0; i < 8; i++) { for (unsigned int i = 0; i < 8; i++) {
double yValue = estimateLuminance(context.frameContext, double yValue = estimateLuminance(context.frameContext,
context.configuration.grid.bdsGrid, context.configuration.grid.bdsGrid,
@ -331,7 +336,7 @@ void Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats)
break; break;
} }
computeExposure(context.frameContext, yGain); computeExposure(context.frameContext, yGain, iqMeanGain);
frameCount_++; frameCount_++;
} }

View file

@ -31,10 +31,11 @@ public:
void process(IPAContext &context, const ipu3_uapi_stats_3a *stats) override; void process(IPAContext &context, const ipu3_uapi_stats_3a *stats) override;
private: private:
void measureBrightness(const ipu3_uapi_stats_3a *stats, double measureBrightness(const ipu3_uapi_stats_3a *stats,
const ipu3_uapi_grid_config &grid); const ipu3_uapi_grid_config &grid) const;
void filterExposure(); void filterExposure();
void computeExposure(IPAFrameContext &frameContext, double yGain); void computeExposure(IPAFrameContext &frameContext, double yGain,
double iqMeanGain);
double estimateLuminance(IPAFrameContext &frameContext, double estimateLuminance(IPAFrameContext &frameContext,
const ipu3_uapi_grid_config &grid, const ipu3_uapi_grid_config &grid,
const ipu3_uapi_stats_3a *stats, const ipu3_uapi_stats_3a *stats,
@ -42,8 +43,6 @@ private:
uint64_t frameCount_; uint64_t frameCount_;
double iqMean_;
utils::Duration lineDuration_; utils::Duration lineDuration_;
utils::Duration minShutterSpeed_; utils::Duration minShutterSpeed_;
utils::Duration maxShutterSpeed_; utils::Duration maxShutterSpeed_;