ipa: rpi: agc: Change handling of colour gains less than 1
Previously these were handled in the AGC/AEC exposure update calculations by explicitly driving a higher digital gain to "cancel out" any colour gains that were less than 1. Now we're ignoring this in the AGC and leaving it to the IPA code to normalise all the gains so that the smallest is 1. We don't regard this as a "real" increase because one of the colour channels (just not necessarily the green one) still gets the minimum gain possible. We do, however, update the statistics calculations so that they reflect any such digital gain increase, so that images are driven to the correct level. Signed-off-by: David Plowman <david.plowman@raspberrypi.com> Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: Naushir Patuck <naush@raspberrypi.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
committed by
Kieran Bingham
parent
9c082483f4
commit
42562d6d33
@@ -435,14 +435,9 @@ void AgcChannel::switchMode(CameraMode const &cameraMode,
|
||||
|
||||
Duration fixedExposureTime = limitExposureTime(fixedExposureTime_);
|
||||
if (fixedExposureTime && fixedAnalogueGain_) {
|
||||
/* We're going to reset the algorithm here with these fixed values. */
|
||||
fetchAwbStatus(metadata);
|
||||
double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
|
||||
ASSERT(minColourGain != 0.0);
|
||||
|
||||
/* This is the equivalent of computeTargetExposure and applyDigitalGain. */
|
||||
target_.totalExposureNoDG = fixedExposureTime_ * fixedAnalogueGain_;
|
||||
target_.totalExposure = target_.totalExposureNoDG / minColourGain;
|
||||
target_.totalExposure = target_.totalExposureNoDG;
|
||||
|
||||
/* Equivalent of filterExposure. This resets any "history". */
|
||||
filtered_ = target_;
|
||||
@@ -462,10 +457,10 @@ void AgcChannel::switchMode(CameraMode const &cameraMode,
|
||||
*/
|
||||
|
||||
double ratio = lastSensitivity / cameraMode.sensitivity;
|
||||
target_.totalExposureNoDG *= ratio;
|
||||
target_.totalExposure *= ratio;
|
||||
filtered_.totalExposureNoDG *= ratio;
|
||||
target_.totalExposureNoDG = target_.totalExposure;
|
||||
filtered_.totalExposure *= ratio;
|
||||
filtered_.totalExposureNoDG = filtered_.totalExposure;
|
||||
|
||||
divideUpExposure();
|
||||
} else {
|
||||
@@ -716,8 +711,13 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb,
|
||||
}
|
||||
|
||||
/* Factor in the AWB correction if needed. */
|
||||
if (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb)
|
||||
sum *= RGB<double>{ { awb.gainR, awb.gainG, awb.gainB } };
|
||||
if (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb) {
|
||||
double minColourGain = std::min({ awb.gainR, awb.gainG, awb.gainB, 1.0 });
|
||||
minColourGain = std::max(minColourGain, 1.0);
|
||||
RGB<double> colourGains{ { awb.gainR, awb.gainG, awb.gainB } };
|
||||
colourGains /= minColourGain;
|
||||
sum *= colourGains;
|
||||
}
|
||||
|
||||
double ySum = ipa::rec601LuminanceFromRGB(sum);
|
||||
|
||||
@@ -797,16 +797,8 @@ void AgcChannel::computeGain(StatisticsPtr &statistics, Metadata *imageMetadata,
|
||||
void AgcChannel::computeTargetExposure(double gain)
|
||||
{
|
||||
if (status_.fixedExposureTime && status_.fixedAnalogueGain) {
|
||||
/*
|
||||
* When analogue gain and exposure time are both fixed, we need
|
||||
* to drive the total exposure so that we end up with a digital
|
||||
* gain of at least 1/minColourGain. Otherwise we'd desaturate
|
||||
* channels causing white to go cyan or magenta.
|
||||
*/
|
||||
double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
|
||||
ASSERT(minColourGain != 0.0);
|
||||
target_.totalExposure =
|
||||
status_.fixedExposureTime * status_.fixedAnalogueGain / minColourGain;
|
||||
status_.fixedExposureTime * status_.fixedAnalogueGain;
|
||||
} else {
|
||||
/*
|
||||
* The statistics reflect the image without digital gain, so the final
|
||||
@@ -867,15 +859,8 @@ bool AgcChannel::applyChannelConstraints(const AgcChannelTotalExposures &channel
|
||||
|
||||
bool AgcChannel::applyDigitalGain(double gain, double targetY, bool channelBound)
|
||||
{
|
||||
double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
|
||||
ASSERT(minColourGain != 0.0);
|
||||
double dg = 1.0 / minColourGain;
|
||||
/*
|
||||
* I think this pipeline subtracts black level and rescales before we
|
||||
* get the stats, so no need to worry about it.
|
||||
*/
|
||||
LOG(RPiAgc, Debug) << "after AWB, target dg " << dg << " gain " << gain
|
||||
<< " target_Y " << targetY;
|
||||
double dg = 1.0;
|
||||
|
||||
/*
|
||||
* Finally, if we're trying to reduce exposure but the target_Y is
|
||||
* "close" to 1.0, then the gain computed for that constraint will be
|
||||
|
||||
Reference in New Issue
Block a user