libipa: exposure_mode_helper: Calculate quantization gain in splitExposure()
Calculate the error introduced by quantization as "quantization gain" and return it separately from splitExposure(). It is not included in the digital gain, to not silently ignore the limits imposed by the AGC configuration. Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
committed by
Kieran Bingham
parent
0ba6d930de
commit
57a46118a8
@@ -222,8 +222,8 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
|
||||
utils::Duration effectiveExposureValue = exposureTime * analogueGain;
|
||||
|
||||
utils::Duration newExposureTime;
|
||||
double aGain, dGain;
|
||||
std::tie(newExposureTime, aGain, dGain) =
|
||||
double aGain, qGain, dGain;
|
||||
std::tie(newExposureTime, aGain, qGain, dGain) =
|
||||
calculateNewEv(context.activeState.agc.constraintMode,
|
||||
context.activeState.agc.exposureMode, hist,
|
||||
effectiveExposureValue);
|
||||
|
||||
@@ -566,11 +566,12 @@ utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue)
|
||||
*
|
||||
* Calculate a new exposure value to try to obtain the target. The calculated
|
||||
* exposure value is filtered to prevent rapid changes from frame to frame, and
|
||||
* divided into exposure time, analogue and digital gain.
|
||||
* divided into exposure time, analogue, quantization and digital gain.
|
||||
*
|
||||
* \return Tuple of exposure time, analogue gain, and digital gain
|
||||
* \return Tuple of exposure time, analogue gain, quantization gain and digital
|
||||
* gain
|
||||
*/
|
||||
std::tuple<utils::Duration, double, double>
|
||||
std::tuple<utils::Duration, double, double, double>
|
||||
AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex,
|
||||
uint32_t exposureModeIndex,
|
||||
const Histogram &yHist,
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
return controls_;
|
||||
}
|
||||
|
||||
std::tuple<utils::Duration, double, double>
|
||||
std::tuple<utils::Duration, double, double, double>
|
||||
calculateNewEv(uint32_t constraintModeIndex, uint32_t exposureModeIndex,
|
||||
const Histogram &yHist, utils::Duration effectiveExposureValue);
|
||||
|
||||
|
||||
@@ -178,14 +178,24 @@ double ExposureModeHelper::clampGain(double gain, double *quantizationGain) cons
|
||||
* required exposure, the helper falls-back to simply maximising the exposure
|
||||
* time first, followed by analogue gain, followed by digital gain.
|
||||
*
|
||||
* \return Tuple of exposure time, analogue gain, and digital gain
|
||||
* During the calculations the gain missed due to quantization is recorded and
|
||||
* returned as quantization gain. The quantization gain is not included in the
|
||||
* digital gain. So to exactly apply the given exposure, both quantization gain
|
||||
* and digital gain must be applied.
|
||||
*
|
||||
* \return Tuple of exposure time, analogue gain, quantization gain and digital
|
||||
* gain
|
||||
*/
|
||||
std::tuple<utils::Duration, double, double>
|
||||
std::tuple<utils::Duration, double, double, double>
|
||||
ExposureModeHelper::splitExposure(utils::Duration exposure) const
|
||||
{
|
||||
ASSERT(maxExposureTime_);
|
||||
ASSERT(maxGain_);
|
||||
|
||||
utils::Duration exposureTime;
|
||||
double gain;
|
||||
double quantGain;
|
||||
double quantGain2;
|
||||
bool gainFixed = minGain_ == maxGain_;
|
||||
bool exposureTimeFixed = minExposureTime_ == maxExposureTime_;
|
||||
|
||||
@@ -193,16 +203,21 @@ ExposureModeHelper::splitExposure(utils::Duration exposure) const
|
||||
* There's no point entering the loop if we cannot change either gain
|
||||
* nor exposure time anyway.
|
||||
*/
|
||||
if (exposureTimeFixed && gainFixed)
|
||||
return { minExposureTime_, minGain_, exposure / (minExposureTime_ * minGain_) };
|
||||
if (exposureTimeFixed && gainFixed) {
|
||||
exposureTime = clampExposureTime(minExposureTime_, &quantGain);
|
||||
gain = clampGain(minGain_, &quantGain2);
|
||||
quantGain *= quantGain2;
|
||||
|
||||
return { exposureTime, gain, quantGain,
|
||||
exposure / (exposureTime * gain * quantGain) };
|
||||
}
|
||||
|
||||
utils::Duration exposureTime;
|
||||
double stageGain = clampGain(1.0);
|
||||
double lastStageGain = stageGain;
|
||||
double gain;
|
||||
|
||||
for (unsigned int stage = 0; stage < gains_.size(); stage++) {
|
||||
utils::Duration stageExposureTime = clampExposureTime(exposureTimes_[stage]);
|
||||
utils::Duration stageExposureTime = clampExposureTime(exposureTimes_[stage],
|
||||
&quantGain);
|
||||
stageGain = clampGain(gains_[stage]);
|
||||
|
||||
/*
|
||||
@@ -215,18 +230,22 @@ ExposureModeHelper::splitExposure(utils::Duration exposure) const
|
||||
|
||||
/* Clamp the gain to lastStageGain and regulate exposureTime. */
|
||||
if (stageExposureTime * lastStageGain >= exposure) {
|
||||
exposureTime = clampExposureTime(exposure / lastStageGain);
|
||||
gain = clampGain(exposure / exposureTime);
|
||||
exposureTime = clampExposureTime(exposure / lastStageGain, &quantGain);
|
||||
gain = clampGain(exposure / exposureTime, &quantGain2);
|
||||
quantGain *= quantGain2;
|
||||
|
||||
return { exposureTime, gain, exposure / (exposureTime * gain) };
|
||||
return { exposureTime, gain, quantGain,
|
||||
exposure / (exposureTime * gain * quantGain) };
|
||||
}
|
||||
|
||||
/* Clamp the exposureTime to stageExposureTime and regulate gain. */
|
||||
if (stageExposureTime * stageGain >= exposure) {
|
||||
exposureTime = stageExposureTime;
|
||||
gain = clampGain(exposure / exposureTime);
|
||||
gain = clampGain(exposure / exposureTime, &quantGain2);
|
||||
quantGain *= quantGain2;
|
||||
|
||||
return { exposureTime, gain, exposure / (exposureTime * gain) };
|
||||
return { exposureTime, gain, quantGain,
|
||||
exposure / (exposureTime * gain * quantGain) };
|
||||
}
|
||||
|
||||
lastStageGain = stageGain;
|
||||
@@ -239,10 +258,12 @@ ExposureModeHelper::splitExposure(utils::Duration exposure) const
|
||||
* stages to use then the default stageGain of 1.0 is used so that
|
||||
* exposure time is maxed before gain is touched at all.
|
||||
*/
|
||||
exposureTime = clampExposureTime(exposure / stageGain);
|
||||
gain = clampGain(exposure / exposureTime);
|
||||
exposureTime = clampExposureTime(exposure / stageGain, &quantGain);
|
||||
gain = clampGain(exposure / exposureTime, &quantGain2);
|
||||
quantGain *= quantGain2;
|
||||
|
||||
return { exposureTime, gain, exposure / (exposureTime * gain) };
|
||||
return { exposureTime, gain, quantGain,
|
||||
exposure / (exposureTime * gain * quantGain) };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime,
|
||||
double minGain, double maxGain);
|
||||
|
||||
std::tuple<utils::Duration, double, double>
|
||||
std::tuple<utils::Duration, double, double, double>
|
||||
splitExposure(utils::Duration exposure) const;
|
||||
|
||||
utils::Duration minExposureTime() const { return minExposureTime_; }
|
||||
|
||||
@@ -381,8 +381,8 @@ void Agc::process(IPAContext &context,
|
||||
utils::Duration effectiveExposureValue = currentShutter * totalGain;
|
||||
|
||||
utils::Duration shutterTime;
|
||||
double aGain, dGain;
|
||||
std::tie(shutterTime, aGain, dGain) =
|
||||
double aGain, qGain, dGain;
|
||||
std::tie(shutterTime, aGain, qGain, dGain) =
|
||||
calculateNewEv(activeState.agc.constraintMode,
|
||||
activeState.agc.exposureMode, statistics_.yHist,
|
||||
effectiveExposureValue);
|
||||
|
||||
@@ -567,15 +567,16 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
|
||||
setExposureCompensation(pow(2.0, frameContext.agc.exposureValue));
|
||||
|
||||
utils::Duration newExposureTime;
|
||||
double aGain, dGain;
|
||||
std::tie(newExposureTime, aGain, dGain) =
|
||||
double aGain, qGain, dGain;
|
||||
std::tie(newExposureTime, aGain, qGain, dGain) =
|
||||
calculateNewEv(frameContext.agc.constraintMode,
|
||||
frameContext.agc.exposureMode,
|
||||
hist, effectiveExposureValue);
|
||||
|
||||
LOG(RkISP1Agc, Debug)
|
||||
<< "Divided up exposure time, analogue gain and digital gain are "
|
||||
<< newExposureTime << ", " << aGain << " and " << dGain;
|
||||
<< "Divided up exposure time, analogue gain, quantization gain"
|
||||
<< " and digital gain are " << newExposureTime << ", " << aGain
|
||||
<< ", " << qGain << " and " << dGain;
|
||||
|
||||
IPAActiveState &activeState = context.activeState;
|
||||
/* Update the estimated exposure and gain. */
|
||||
|
||||
Reference in New Issue
Block a user