summaryrefslogtreecommitdiff
path: root/src/ipa/rpi/controller
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa/rpi/controller')
-rw-r--r--src/ipa/rpi/controller/histogram.cpp6
-rw-r--r--src/ipa/rpi/controller/rpi/af.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/agc_channel.cpp7
-rw-r--r--src/ipa/rpi/controller/rpi/alsc.cpp18
-rw-r--r--src/ipa/rpi/controller/rpi/awb.cpp36
-rw-r--r--src/ipa/rpi/controller/rpi/awb.h4
-rw-r--r--src/ipa/rpi/controller/rpi/black_level.cpp1
-rw-r--r--src/ipa/rpi/controller/rpi/lux.cpp1
-rw-r--r--src/ipa/rpi/controller/rpi/noise.cpp4
-rw-r--r--src/ipa/rpi/controller/rpi/sharpen.cpp4
10 files changed, 57 insertions, 26 deletions
diff --git a/src/ipa/rpi/controller/histogram.cpp b/src/ipa/rpi/controller/histogram.cpp
index ba5b25dd..13089839 100644
--- a/src/ipa/rpi/controller/histogram.cpp
+++ b/src/ipa/rpi/controller/histogram.cpp
@@ -4,7 +4,7 @@
*
* histogram calculations
*/
-#include <math.h>
+#include <cmath>
#include <stdio.h>
#include "histogram.h"
@@ -49,9 +49,9 @@ double Histogram::interBinMean(double binLo, double binHi) const
{
assert(binHi >= binLo);
double sumBinFreq = 0, cumulFreq = 0;
- for (double binNext = floor(binLo) + 1.0; binNext <= ceil(binHi);
+ for (double binNext = std::floor(binLo) + 1.0; binNext <= std::ceil(binHi);
binLo = binNext, binNext += 1.0) {
- int bin = floor(binLo);
+ int bin = std::floor(binLo);
double freq = (cumulative_[bin + 1] - cumulative_[bin]) *
(std::min(binNext, binHi) - binLo);
sumBinFreq += bin * freq;
diff --git a/src/ipa/rpi/controller/rpi/af.cpp b/src/ipa/rpi/controller/rpi/af.cpp
index 5ca76dd9..2157eb94 100644
--- a/src/ipa/rpi/controller/rpi/af.cpp
+++ b/src/ipa/rpi/controller/rpi/af.cpp
@@ -7,8 +7,8 @@
#include "af.h"
+#include <cmath>
#include <iomanip>
-#include <math.h>
#include <stdlib.h>
#include <libcamera/base/log.h>
diff --git a/src/ipa/rpi/controller/rpi/agc_channel.cpp b/src/ipa/rpi/controller/rpi/agc_channel.cpp
index cf2565a8..c9df9b5b 100644
--- a/src/ipa/rpi/controller/rpi/agc_channel.cpp
+++ b/src/ipa/rpi/controller/rpi/agc_channel.cpp
@@ -883,11 +883,14 @@ void AgcChannel::filterExposure()
/*
* AGC adapts instantly if both shutter and gain are directly specified
- * or we're in the startup phase.
+ * or we're in the startup phase. Also disable the stable region, because we want
+ * to reflect any user exposure/gain updates, however small.
*/
if ((status_.fixedShutter && status_.fixedAnalogueGain) ||
- frameCount_ <= config_.startupFrames)
+ frameCount_ <= config_.startupFrames) {
speed = 1.0;
+ stableRegion = 0.0;
+ }
if (!filtered_.totalExposure) {
filtered_.totalExposure = target_.totalExposure;
} else if (filtered_.totalExposure * (1.0 - stableRegion) < target_.totalExposure &&
diff --git a/src/ipa/rpi/controller/rpi/alsc.cpp b/src/ipa/rpi/controller/rpi/alsc.cpp
index 161fd455..21edb819 100644
--- a/src/ipa/rpi/controller/rpi/alsc.cpp
+++ b/src/ipa/rpi/controller/rpi/alsc.cpp
@@ -6,8 +6,8 @@
*/
#include <algorithm>
+#include <cmath>
#include <functional>
-#include <math.h>
#include <numeric>
#include <vector>
@@ -252,12 +252,12 @@ static bool compareModes(CameraMode const &cm0, CameraMode const &cm1)
*/
if (cm0.transform != cm1.transform)
return true;
- int leftDiff = abs(cm0.cropX - cm1.cropX);
- int topDiff = abs(cm0.cropY - cm1.cropY);
- int rightDiff = fabs(cm0.cropX + cm0.scaleX * cm0.width -
- cm1.cropX - cm1.scaleX * cm1.width);
- int bottomDiff = fabs(cm0.cropY + cm0.scaleY * cm0.height -
- cm1.cropY - cm1.scaleY * cm1.height);
+ int leftDiff = std::abs(cm0.cropX - cm1.cropX);
+ int topDiff = std::abs(cm0.cropY - cm1.cropY);
+ int rightDiff = std::abs(cm0.cropX + cm0.scaleX * cm0.width -
+ cm1.cropX - cm1.scaleX * cm1.width);
+ int bottomDiff = std::abs(cm0.cropY + cm0.scaleY * cm0.height -
+ cm1.cropY - cm1.scaleY * cm1.height);
/*
* These thresholds are a rather arbitrary amount chosen to trigger
* when carrying on with the previously calculated tables might be
@@ -732,7 +732,7 @@ static double gaussSeidel2Sor(const SparseArray<double> &M, double omega,
double maxDiff = 0;
for (i = 0; i < XY; i++) {
lambda[i] = oldLambda[i] + (lambda[i] - oldLambda[i]) * omega;
- if (fabs(lambda[i] - oldLambda[i]) > fabs(maxDiff))
+ if (std::abs(lambda[i] - oldLambda[i]) > std::abs(maxDiff))
maxDiff = lambda[i] - oldLambda[i];
}
return maxDiff;
@@ -764,7 +764,7 @@ static void runMatrixIterations(const Array2D<double> &C,
constructM(C, W, M);
double lastMaxDiff = std::numeric_limits<double>::max();
for (unsigned int i = 0; i < nIter; i++) {
- double maxDiff = fabs(gaussSeidel2Sor(M, omega, lambda, lambdaBound));
+ double maxDiff = std::abs(gaussSeidel2Sor(M, omega, lambda, lambdaBound));
if (maxDiff < threshold) {
LOG(RPiAlsc, Debug)
<< "Stop after " << i + 1 << " iterations";
diff --git a/src/ipa/rpi/controller/rpi/awb.cpp b/src/ipa/rpi/controller/rpi/awb.cpp
index f45525bc..9d8e170d 100644
--- a/src/ipa/rpi/controller/rpi/awb.cpp
+++ b/src/ipa/rpi/controller/rpi/awb.cpp
@@ -6,6 +6,7 @@
*/
#include <assert.h>
+#include <cmath>
#include <functional>
#include <libcamera/base/log.h>
@@ -20,6 +21,8 @@ using namespace libcamera;
LOG_DEFINE_CATEGORY(RPiAwb)
+constexpr double kDefaultCT = 4500.0;
+
#define NAME "rpi.awb"
/*
@@ -167,6 +170,14 @@ int AwbConfig::read(const libcamera::YamlObject &params)
whitepointB = params["whitepoint_b"].get<double>(0.0);
if (bayes == false)
sensitivityR = sensitivityB = 1.0; /* nor do sensitivities make any sense */
+ /*
+ * The biasProportion parameter adds a small proportion of the counted
+ * pixles to a region biased to the biasCT colour temperature.
+ *
+ * A typical value for biasProportion would be between 0.05 to 0.1.
+ */
+ biasProportion = params["bias_proportion"].get<double>(0.0);
+ biasCT = params["bias_ct"].get<double>(kDefaultCT);
return 0;
}
@@ -214,7 +225,7 @@ void Awb::initialise()
syncResults_.gainB = 1.0 / config_.ctB.eval(syncResults_.temperatureK);
} else {
/* random values just to stop the world blowing up */
- syncResults_.temperatureK = 4500;
+ syncResults_.temperatureK = kDefaultCT;
syncResults_.gainR = syncResults_.gainG = syncResults_.gainB = 1.0;
}
prevSyncResults_ = syncResults_;
@@ -407,7 +418,8 @@ void Awb::asyncFunc()
static void generateStats(std::vector<Awb::RGB> &zones,
StatisticsPtr &stats, double minPixels,
- double minG, Metadata &globalMetadata)
+ double minG, Metadata &globalMetadata,
+ double biasProportion, double biasCtR, double biasCtB)
{
std::scoped_lock<RPiController::Metadata> l(globalMetadata);
@@ -420,6 +432,14 @@ static void generateStats(std::vector<Awb::RGB> &zones,
continue;
zone.R = region.val.rSum / region.counted;
zone.B = region.val.bSum / region.counted;
+ /*
+ * Add some bias samples to allow the search to tend to a
+ * bias CT in failure cases.
+ */
+ const unsigned int proportion = biasProportion * region.counted;
+ zone.R += proportion * biasCtR;
+ zone.B += proportion * biasCtB;
+ zone.G += proportion * 1.0;
/* Factor in the ALSC applied colour shading correction if required. */
const AlscStatus *alscStatus = globalMetadata.getLocked<AlscStatus>("alsc.status");
if (stats->colourStatsPos == Statistics::ColourStatsPos::PreLsc && alscStatus) {
@@ -440,7 +460,9 @@ void Awb::prepareStats()
* any LSC compensation. We also ignore config_.fast in this version.
*/
generateStats(zones_, statistics_, config_.minPixels,
- config_.minG, getGlobalMetadata());
+ config_.minG, getGlobalMetadata(),
+ config_.biasProportion, config_.ctR.eval(config_.biasCT),
+ config_.ctB.eval(config_.biasCT));
/*
* apply sensitivities, so values appear to come from our "canonical"
* sensor.
@@ -505,7 +527,7 @@ static double interpolateQuadatric(ipa::Pwl::Point const &a, ipa::Pwl::Point con
const double eps = 1e-3;
ipa::Pwl::Point ca = c - a, ba = b - a;
double denominator = 2 * (ba.y() * ca.x() - ca.y() * ba.x());
- if (abs(denominator) > eps) {
+ if (std::abs(denominator) > eps) {
double numerator = ba.y() * ca.x() * ca.x() - ca.y() * ba.x() * ba.x();
double result = numerator / denominator + a.x();
return std::max(a.x(), std::min(c.x(), result));
@@ -716,7 +738,11 @@ void Awb::awbGrey()
sumR += *ri, sumB += *bi;
double gainR = sumR.G / (sumR.R + 1),
gainB = sumB.G / (sumB.B + 1);
- asyncResults_.temperatureK = 4500; /* don't know what it is */
+ /*
+ * The grey world model can't estimate the colour temperature, use a
+ * default value.
+ */
+ asyncResults_.temperatureK = kDefaultCT;
asyncResults_.gainR = gainR;
asyncResults_.gainG = 1.0;
asyncResults_.gainB = gainB;
diff --git a/src/ipa/rpi/controller/rpi/awb.h b/src/ipa/rpi/controller/rpi/awb.h
index ab30f4fa..5d628b47 100644
--- a/src/ipa/rpi/controller/rpi/awb.h
+++ b/src/ipa/rpi/controller/rpi/awb.h
@@ -87,6 +87,10 @@ struct AwbConfig {
double whitepointR;
double whitepointB;
bool bayes; /* use Bayesian algorithm */
+ /* proportion of counted samples to add for the search bias */
+ double biasProportion;
+ /* CT target for the search bias */
+ double biasCT;
};
class Awb : public AwbAlgorithm
diff --git a/src/ipa/rpi/controller/rpi/black_level.cpp b/src/ipa/rpi/controller/rpi/black_level.cpp
index ea991df9..4c968f14 100644
--- a/src/ipa/rpi/controller/rpi/black_level.cpp
+++ b/src/ipa/rpi/controller/rpi/black_level.cpp
@@ -5,7 +5,6 @@
* black level control algorithm
*/
-#include <math.h>
#include <stdint.h>
#include <libcamera/base/log.h>
diff --git a/src/ipa/rpi/controller/rpi/lux.cpp b/src/ipa/rpi/controller/rpi/lux.cpp
index 7b31faab..652d85d7 100644
--- a/src/ipa/rpi/controller/rpi/lux.cpp
+++ b/src/ipa/rpi/controller/rpi/lux.cpp
@@ -4,7 +4,6 @@
*
* Lux control algorithm
*/
-#include <math.h>
#include <libcamera/base/log.h>
diff --git a/src/ipa/rpi/controller/rpi/noise.cpp b/src/ipa/rpi/controller/rpi/noise.cpp
index 3f1c62cf..145175fb 100644
--- a/src/ipa/rpi/controller/rpi/noise.cpp
+++ b/src/ipa/rpi/controller/rpi/noise.cpp
@@ -5,7 +5,7 @@
* Noise control algorithm
*/
-#include <math.h>
+#include <cmath>
#include <libcamera/base/log.h>
@@ -69,7 +69,7 @@ void Noise::prepare(Metadata *imageMetadata)
* make some adjustments based on the camera mode (such as
* binning), if we knew how to discover it...
*/
- double factor = sqrt(deviceStatus.analogueGain) / modeFactor_;
+ double factor = std::sqrt(deviceStatus.analogueGain) / modeFactor_;
struct NoiseStatus status;
status.noiseConstant = referenceConstant_ * factor;
status.noiseSlope = referenceSlope_ * factor;
diff --git a/src/ipa/rpi/controller/rpi/sharpen.cpp b/src/ipa/rpi/controller/rpi/sharpen.cpp
index 39537f4a..1d143ff5 100644
--- a/src/ipa/rpi/controller/rpi/sharpen.cpp
+++ b/src/ipa/rpi/controller/rpi/sharpen.cpp
@@ -5,7 +5,7 @@
* sharpening control algorithm
*/
-#include <math.h>
+#include <cmath>
#include <libcamera/base/log.h>
@@ -68,7 +68,7 @@ void Sharpen::prepare(Metadata *imageMetadata)
* we adjust the limit and threshold less aggressively. Using a sqrt
* function is an arbitrary but gentle way of accomplishing this.
*/
- double userStrengthSqrt = sqrt(userStrength_);
+ double userStrengthSqrt = std::sqrt(userStrength_);
struct SharpenStatus status;
/*
* Binned modes seem to need the sharpening toned down with this