ipa: raspberrypi: agc: Move weights out of AGC

The region weights for the the AGC zones are handled by the AGC
algorithm. Apply them directly in the IPA (vc4.cpp) to the statistics
that we pass to the AGC.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
David Plowman 2023-05-03 13:20:32 +01:00 committed by Laurent Pinchart
parent d903fdbe31
commit 503bebd0ed
4 changed files with 41 additions and 16 deletions

View file

@ -6,6 +6,8 @@
*/ */
#pragma once #pragma once
#include <vector>
#include <libcamera/base/utils.h> #include <libcamera/base/utils.h>
#include "algorithm.h" #include "algorithm.h"
@ -18,6 +20,7 @@ public:
AgcAlgorithm(Controller *controller) : Algorithm(controller) {} AgcAlgorithm(Controller *controller) : Algorithm(controller) {}
/* An AGC algorithm must provide the following: */ /* An AGC algorithm must provide the following: */
virtual unsigned int getConvergenceFrames() const = 0; virtual unsigned int getConvergenceFrames() const = 0;
virtual std::vector<double> const &getWeights() const = 0;
virtual void setEv(double ev) = 0; virtual void setEv(double ev) = 0;
virtual void setFlickerPeriod(libcamera::utils::Duration flickerPeriod) = 0; virtual void setFlickerPeriod(libcamera::utils::Duration flickerPeriod) = 0;
virtual void setFixedShutter(libcamera::utils::Duration fixedShutter) = 0; virtual void setFixedShutter(libcamera::utils::Duration fixedShutter) = 0;

View file

@ -292,6 +292,18 @@ unsigned int Agc::getConvergenceFrames() const
return config_.convergenceFrames; return config_.convergenceFrames;
} }
std::vector<double> const &Agc::getWeights() const
{
/*
* In case someone calls setMeteringMode and then this before the
* algorithm has run and updated the meteringMode_ pointer.
*/
auto it = config_.meteringModes.find(meteringModeName_);
if (it == config_.meteringModes.end())
return meteringMode_->weights;
return it->second.weights;
}
void Agc::setEv(double ev) void Agc::setEv(double ev)
{ {
ev_ = ev; ev_ = ev;
@ -595,19 +607,16 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb,
ASSERT(weights.size() == stats->agcRegions.numRegions()); ASSERT(weights.size() == stats->agcRegions.numRegions());
/* /*
* Note how the calculation below means that equal weights give you * Note that the weights are applied by the IPA to the statistics directly,
* "average" metering (i.e. all pixels equally important). * before they are given to us here.
*/ */
double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0; double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0;
for (unsigned int i = 0; i < stats->agcRegions.numRegions(); i++) { for (unsigned int i = 0; i < stats->agcRegions.numRegions(); i++) {
auto &region = stats->agcRegions.get(i); auto &region = stats->agcRegions.get(i);
double rAcc = std::min<double>(region.val.rSum * gain, (maxVal - 1) * region.counted); rSum += std::min<double>(region.val.rSum * gain, (maxVal - 1) * region.counted);
double gAcc = std::min<double>(region.val.gSum * gain, (maxVal - 1) * region.counted); gSum += std::min<double>(region.val.gSum * gain, (maxVal - 1) * region.counted);
double bAcc = std::min<double>(region.val.bSum * gain, (maxVal - 1) * region.counted); bSum += std::min<double>(region.val.bSum * gain, (maxVal - 1) * region.counted);
rSum += rAcc * weights[i]; pixelSum += region.counted;
gSum += gAcc * weights[i];
bSum += bAcc * weights[i];
pixelSum += region.counted * weights[i];
} }
if (pixelSum == 0.0) { if (pixelSum == 0.0) {
LOG(RPiAgc, Warning) << "computeInitialY: pixelSum is zero"; LOG(RPiAgc, Warning) << "computeInitialY: pixelSum is zero";

View file

@ -69,6 +69,7 @@ public:
char const *name() const override; char const *name() const override;
int read(const libcamera::YamlObject &params) override; int read(const libcamera::YamlObject &params) override;
unsigned int getConvergenceFrames() const override; unsigned int getConvergenceFrames() const override;
std::vector<double> const &getWeights() const override;
void setEv(double ev) override; void setEv(double ev) override;
void setFlickerPeriod(libcamera::utils::Duration flickerPeriod) override; void setFlickerPeriod(libcamera::utils::Duration flickerPeriod) override;
void setMaxShutter(libcamera::utils::Duration maxShutter) override; void setMaxShutter(libcamera::utils::Duration maxShutter) override;

View file

@ -211,13 +211,25 @@ RPiController::StatisticsPtr IpaVc4::platformProcessStats(Span<uint8_t> mem)
stats->awb_stats[i].counted, stats->awb_stats[i].counted,
stats->awb_stats[i].notcounted }); stats->awb_stats[i].notcounted });
RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
controller_.getAlgorithm("agc"));
if (!agc) {
LOG(IPARPI, Debug) << "No AGC algorithm - not copying statistics";
statistics->agcRegions.init(0);
} else {
statistics->agcRegions.init(hw.agcRegions); statistics->agcRegions.init(hw.agcRegions);
for (i = 0; i < statistics->agcRegions.numRegions(); i++) const std::vector<double> &weights = agc->getWeights();
statistics->agcRegions.set(i, { { stats->agc_stats[i].r_sum << scale, for (i = 0; i < statistics->agcRegions.numRegions(); i++) {
stats->agc_stats[i].g_sum << scale, uint64_t rSum = (stats->agc_stats[i].r_sum << scale) * weights[i];
stats->agc_stats[i].b_sum << scale }, uint64_t gSum = (stats->agc_stats[i].g_sum << scale) * weights[i];
stats->agc_stats[i].counted, uint64_t bSum = (stats->agc_stats[i].b_sum << scale) * weights[i];
stats->awb_stats[i].notcounted }); uint32_t counted = stats->agc_stats[i].counted * weights[i];
uint32_t notcounted = stats->agc_stats[i].notcounted * weights[i];
statistics->agcRegions.set(i, { { rSum, gSum, bSum },
counted,
notcounted });
}
}
statistics->focusRegions.init(hw.focusRegions); statistics->focusRegions.init(hw.focusRegions);
for (i = 0; i < statistics->focusRegions.numRegions(); i++) for (i = 0; i < statistics->focusRegions.numRegions(); i++)