summaryrefslogtreecommitdiff
path: root/src/ipa/rpi
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa/rpi')
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_imx283.cpp73
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_imx290.cpp6
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_ov7251.cpp66
-rw-r--r--src/ipa/rpi/cam_helper/meson.build2
-rw-r--r--src/ipa/rpi/common/ipa_base.cpp12
-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
-rw-r--r--src/ipa/rpi/vc4/data/imx283.json313
-rw-r--r--src/ipa/rpi/vc4/data/meson.build2
-rw-r--r--src/ipa/rpi/vc4/data/ov7251_mono.json136
18 files changed, 664 insertions, 29 deletions
diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx283.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx283.cpp
new file mode 100644
index 00000000..cb0be72a
--- /dev/null
+++ b/src/ipa/rpi/cam_helper/cam_helper_imx283.cpp
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2024, Raspberry Pi Ltd
+ *
+ * cam_helper_Imx283.cpp - camera information for Imx283 sensor
+ */
+
+#include <assert.h>
+
+#include "cam_helper.h"
+
+using namespace RPiController;
+
+class CamHelperImx283 : public CamHelper
+{
+public:
+ CamHelperImx283();
+ uint32_t gainCode(double gain) const override;
+ double gain(uint32_t gainCode) const override;
+ void getDelays(int &exposureDelay, int &gainDelay,
+ int &vblankDelay, int &hblankDelay) const override;
+ unsigned int hideFramesModeSwitch() const override;
+
+private:
+ /*
+ * Smallest difference between the frame length and integration time,
+ * in units of lines.
+ */
+ static constexpr int frameIntegrationDiff = 4;
+};
+
+/*
+ * Imx283 doesn't output metadata, so we have to use the delayed controls which
+ * works by counting frames.
+ */
+
+CamHelperImx283::CamHelperImx283()
+ : CamHelper({}, frameIntegrationDiff)
+{
+}
+
+uint32_t CamHelperImx283::gainCode(double gain) const
+{
+ return static_cast<uint32_t>(2048.0 - 2048.0 / gain);
+}
+
+double CamHelperImx283::gain(uint32_t gainCode) const
+{
+ return static_cast<double>(2048.0 / (2048 - gainCode));
+}
+
+void CamHelperImx283::getDelays(int &exposureDelay, int &gainDelay,
+ int &vblankDelay, int &hblankDelay) const
+{
+ /* The driver appears to behave as follows: */
+ exposureDelay = 2;
+ gainDelay = 2;
+ vblankDelay = 2;
+ hblankDelay = 2;
+}
+
+unsigned int CamHelperImx283::hideFramesModeSwitch() const
+{
+ /* After a mode switch, we seem to get 1 bad frame. */
+ return 1;
+}
+
+static CamHelper *create()
+{
+ return new CamHelperImx283();
+}
+
+static RegisterCamHelper reg("imx283", &create);
diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx290.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx290.cpp
index 24275e12..e57ab538 100644
--- a/src/ipa/rpi/cam_helper/cam_helper_imx290.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper_imx290.cpp
@@ -5,7 +5,7 @@
* camera helper for imx290 sensor
*/
-#include <math.h>
+#include <cmath>
#include "cam_helper.h"
@@ -37,13 +37,13 @@ CamHelperImx290::CamHelperImx290()
uint32_t CamHelperImx290::gainCode(double gain) const
{
- int code = 66.6667 * log10(gain);
+ int code = 66.6667 * std::log10(gain);
return std::max(0, std::min(code, 0xf0));
}
double CamHelperImx290::gain(uint32_t gainCode) const
{
- return pow(10, 0.015 * gainCode);
+ return std::pow(10, 0.015 * gainCode);
}
void CamHelperImx290::getDelays(int &exposureDelay, int &gainDelay,
diff --git a/src/ipa/rpi/cam_helper/cam_helper_ov7251.cpp b/src/ipa/rpi/cam_helper/cam_helper_ov7251.cpp
new file mode 100644
index 00000000..7b12c445
--- /dev/null
+++ b/src/ipa/rpi/cam_helper/cam_helper_ov7251.cpp
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2021, Raspberry Pi Ltd
+ *
+ * camera information for ov7251 sensor
+ */
+
+#include <assert.h>
+
+#include "cam_helper.h"
+
+using namespace RPiController;
+
+class CamHelperOv7251 : public CamHelper
+{
+public:
+ CamHelperOv7251();
+ uint32_t gainCode(double gain) const override;
+ double gain(uint32_t gainCode) const override;
+ void getDelays(int &exposureDelay, int &gainDelay,
+ int &vblankDelay, int &hblankDelay) const override;
+
+private:
+ /*
+ * Smallest difference between the frame length and integration time,
+ * in units of lines.
+ */
+ static constexpr int frameIntegrationDiff = 4;
+};
+
+/*
+ * OV7251 doesn't output metadata, so we have to use the "unicam parser" which
+ * works by counting frames.
+ */
+
+CamHelperOv7251::CamHelperOv7251()
+ : CamHelper({}, frameIntegrationDiff)
+{
+}
+
+uint32_t CamHelperOv7251::gainCode(double gain) const
+{
+ return static_cast<uint32_t>(gain * 16.0);
+}
+
+double CamHelperOv7251::gain(uint32_t gainCode) const
+{
+ return static_cast<double>(gainCode) / 16.0;
+}
+
+void CamHelperOv7251::getDelays(int &exposureDelay, int &gainDelay,
+ int &vblankDelay, int &hblankDelay) const
+{
+ /* The driver appears to behave as follows: */
+ exposureDelay = 2;
+ gainDelay = 2;
+ vblankDelay = 2;
+ hblankDelay = 2;
+}
+
+static CamHelper *create()
+{
+ return new CamHelperOv7251();
+}
+
+static RegisterCamHelper reg("ov7251", &create);
diff --git a/src/ipa/rpi/cam_helper/meson.build b/src/ipa/rpi/cam_helper/meson.build
index 72625057..03e88fe0 100644
--- a/src/ipa/rpi/cam_helper/meson.build
+++ b/src/ipa/rpi/cam_helper/meson.build
@@ -4,12 +4,14 @@ rpi_ipa_cam_helper_sources = files([
'cam_helper.cpp',
'cam_helper_ov5647.cpp',
'cam_helper_imx219.cpp',
+ 'cam_helper_imx283.cpp',
'cam_helper_imx290.cpp',
'cam_helper_imx296.cpp',
'cam_helper_imx477.cpp',
'cam_helper_imx519.cpp',
'cam_helper_imx708.cpp',
'cam_helper_ov64a40.cpp',
+ 'cam_helper_ov7251.cpp',
'cam_helper_ov9281.cpp',
'md_parser_smia.cpp',
])
diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp
index ee3848b5..468f36a8 100644
--- a/src/ipa/rpi/common/ipa_base.cpp
+++ b/src/ipa/rpi/common/ipa_base.cpp
@@ -96,6 +96,13 @@ const ControlInfoMap::Map ipaAfControls{
{ &controls::LensPosition, ControlInfo(0.0f, 32.0f, 1.0f) }
};
+/* Platform specific controls */
+const std::map<const std::string, ControlInfoMap::Map> platformControls {
+ { "pisp", {
+ { &controls::rpi::ScalerCrops, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) }
+ } },
+};
+
} /* namespace */
LOG_DEFINE_CATEGORY(IPARPI)
@@ -159,6 +166,10 @@ int32_t IpaBase::init(const IPASettings &settings, const InitParams &params, Ini
if (lensPresent_)
ctrlMap.merge(ControlInfoMap::Map(ipaAfControls));
+ auto platformCtrlsIt = platformControls.find(controller_.getTarget());
+ if (platformCtrlsIt != platformControls.end())
+ ctrlMap.merge(ControlInfoMap::Map(platformCtrlsIt->second));
+
monoSensor_ = params.sensorInfo.cfaPattern == properties::draft::ColorFilterArrangementEnum::MONO;
if (!monoSensor_)
ctrlMap.merge(ControlInfoMap::Map(ipaColourControls));
@@ -1070,6 +1081,7 @@ void IpaBase::applyControls(const ControlList &controls)
break;
}
+ case controls::rpi::SCALER_CROPS:
case controls::SCALER_CROP: {
/* We do nothing with this, but should avoid the warning below. */
break;
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
diff --git a/src/ipa/rpi/vc4/data/imx283.json b/src/ipa/rpi/vc4/data/imx283.json
new file mode 100644
index 00000000..bfacecc8
--- /dev/null
+++ b/src/ipa/rpi/vc4/data/imx283.json
@@ -0,0 +1,313 @@
+{
+ "version": 2.0,
+ "target": "bcm2835",
+ "algorithms": [
+ {
+ "rpi.black_level":
+ {
+ "black_level": 3200
+ }
+ },
+ {
+ "rpi.dpc": { }
+ },
+ {
+ "rpi.lux":
+ {
+ "reference_shutter_speed": 2461,
+ "reference_gain": 1.0,
+ "reference_aperture": 1.0,
+ "reference_lux": 1148,
+ "reference_Y": 13314
+ }
+ },
+ {
+ "rpi.noise":
+ {
+ "reference_constant": 0,
+ "reference_slope": 2.204
+ }
+ },
+ {
+ "rpi.geq":
+ {
+ "offset": 199,
+ "slope": 0.01947
+ }
+ },
+ {
+ "rpi.sdn": { }
+ },
+ {
+ "rpi.awb":
+ {
+ "priors": [
+ {
+ "lux": 0,
+ "prior":
+ [
+ 2000, 1.0,
+ 3000, 0.0,
+ 13000, 0.0
+ ]
+ },
+ {
+ "lux": 800,
+ "prior":
+ [
+ 2000, 0.0,
+ 6000, 2.0,
+ 13000, 2.0
+ ]
+ },
+ {
+ "lux": 1500,
+ "prior":
+ [
+ 2000, 0.0,
+ 4000, 1.0,
+ 6000, 6.0,
+ 6500, 7.0,
+ 7000, 1.0,
+ 13000, 1.0
+ ]
+ }
+ ],
+ "modes":
+ {
+ "auto":
+ {
+ "lo": 2500,
+ "hi": 8000
+ },
+ "incandescent":
+ {
+ "lo": 2500,
+ "hi": 3000
+ },
+ "tungsten":
+ {
+ "lo": 3000,
+ "hi": 3500
+ },
+ "fluorescent":
+ {
+ "lo": 4000,
+ "hi": 4700
+ },
+ "indoor":
+ {
+ "lo": 3000,
+ "hi": 5000
+ },
+ "daylight":
+ {
+ "lo": 5500,
+ "hi": 6500
+ }
+ },
+ "bayes": 1,
+ "ct_curve":
+ [
+ 2213.0, 0.9607, 0.2593,
+ 5313.0, 0.4822, 0.5909,
+ 6237.0, 0.4739, 0.6308
+ ],
+ "sensitivity_r": 1.0,
+ "sensitivity_b": 1.0,
+ "transverse_pos": 0.0144,
+ "transverse_neg": 0.01
+ }
+ },
+ {
+ "rpi.agc":
+ {
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ }
+ },
+ {
+ "rpi.alsc":
+ {
+ "omega": 1.3,
+ "n_iter": 100,
+ "luminance_strength": 0.7
+ }
+ },
+ {
+ "rpi.contrast":
+ {
+ "ce_enable": 1,
+ "gamma_curve":
+ [
+ 0, 0,
+ 1024, 5040,
+ 2048, 9338,
+ 3072, 12356,
+ 4096, 15312,
+ 5120, 18051,
+ 6144, 20790,
+ 7168, 23193,
+ 8192, 25744,
+ 9216, 27942,
+ 10240, 30035,
+ 11264, 32005,
+ 12288, 33975,
+ 13312, 35815,
+ 14336, 37600,
+ 15360, 39168,
+ 16384, 40642,
+ 18432, 43379,
+ 20480, 45749,
+ 22528, 47753,
+ 24576, 49621,
+ 26624, 51253,
+ 28672, 52698,
+ 30720, 53796,
+ 32768, 54876,
+ 36864, 57012,
+ 40960, 58656,
+ 45056, 59954,
+ 49152, 61183,
+ 53248, 62355,
+ 57344, 63419,
+ 61440, 64476,
+ 65535, 65535
+ ]
+ }
+ },
+ {
+ "rpi.ccm":
+ {
+ "ccms": [
+ {
+ "ct": 2213,
+ "ccm":
+ [
+ 1.91264, -0.27609, -0.63655,
+ -0.65708, 2.11718, -0.46009,
+ 0.03629, -1.38441, 2.34811
+ ]
+ },
+ {
+ "ct": 2255,
+ "ccm":
+ [
+ 1.90369, -0.29309, -0.61059,
+ -0.64693, 2.08169, -0.43476,
+ 0.04086, -1.29999, 2.25914
+ ]
+ },
+ {
+ "ct": 2259,
+ "ccm":
+ [
+ 1.92762, -0.35134, -0.57628,
+ -0.63523, 2.08481, -0.44958,
+ 0.06754, -1.32953, 2.26199
+ ]
+ },
+ {
+ "ct": 5313,
+ "ccm":
+ [
+ 1.75924, -0.54053, -0.21871,
+ -0.38159, 1.88671, -0.50511,
+ -0.00747, -0.53492, 1.54239
+ ]
+ },
+ {
+ "ct": 6237,
+ "ccm":
+ [
+ 2.19299, -0.74764, -0.44536,
+ -0.51678, 2.27651, -0.75972,
+ -0.06498, -0.74269, 1.80767
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "rpi.sharpen": { }
+ }
+ ]
+}
diff --git a/src/ipa/rpi/vc4/data/meson.build b/src/ipa/rpi/vc4/data/meson.build
index afbf875a..8c34a1a5 100644
--- a/src/ipa/rpi/vc4/data/meson.build
+++ b/src/ipa/rpi/vc4/data/meson.build
@@ -3,6 +3,7 @@
conf_files = files([
'imx219.json',
'imx219_noir.json',
+ 'imx283.json',
'imx290.json',
'imx296.json',
'imx296_mono.json',
@@ -18,6 +19,7 @@ conf_files = files([
'ov5647.json',
'ov5647_noir.json',
'ov64a40.json',
+ 'ov7251_mono.json',
'ov9281_mono.json',
'se327m12.json',
'uncalibrated.json',
diff --git a/src/ipa/rpi/vc4/data/ov7251_mono.json b/src/ipa/rpi/vc4/data/ov7251_mono.json
new file mode 100644
index 00000000..a9d05a01
--- /dev/null
+++ b/src/ipa/rpi/vc4/data/ov7251_mono.json
@@ -0,0 +1,136 @@
+{
+ "version": 2.0,
+ "target": "bcm2835",
+ "algorithms": [
+ {
+ "rpi.black_level":
+ {
+ "black_level": 4096
+ }
+ },
+ {
+ "rpi.lux":
+ {
+ "reference_shutter_speed": 2000,
+ "reference_gain": 1.0,
+ "reference_aperture": 1.0,
+ "reference_lux": 800,
+ "reference_Y": 20000
+ }
+ },
+ {
+ "rpi.noise":
+ {
+ "reference_constant": 0,
+ "reference_slope": 2.5
+ }
+ },
+ {
+ "rpi.sdn": { }
+ },
+ {
+ "rpi.agc":
+ {
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 3.0, 4.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 30000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.4,
+ 1000, 0.4
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ }
+ },
+ {
+ "rpi.alsc":
+ {
+ "n_iter": 0,
+ "luminance_strength": 1.0,
+ "corner_strength": 1.5
+ }
+ },
+ {
+ "rpi.contrast":
+ {
+ "ce_enable": 0,
+ "gamma_curve":
+ [
+ 0, 0,
+ 1024, 5040,
+ 2048, 9338,
+ 3072, 12356,
+ 4096, 15312,
+ 5120, 18051,
+ 6144, 20790,
+ 7168, 23193,
+ 8192, 25744,
+ 9216, 27942,
+ 10240, 30035,
+ 11264, 32005,
+ 12288, 33975,
+ 13312, 35815,
+ 14336, 37600,
+ 15360, 39168,
+ 16384, 40642,
+ 18432, 43379,
+ 20480, 45749,
+ 22528, 47753,
+ 24576, 49621,
+ 26624, 51253,
+ 28672, 52698,
+ 30720, 53796,
+ 32768, 54876,
+ 36864, 57012,
+ 40960, 58656,
+ 45056, 59954,
+ 49152, 61183,
+ 53248, 62355,
+ 57344, 63419,
+ 61440, 64476,
+ 65535, 65535
+ ]
+ }
+ }
+ ]
+} \ No newline at end of file