summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ipa/rpi/controller/denoise_algorithm.h4
-rw-r--r--src/ipa/rpi/controller/rpi/denoise.cpp130
-rw-r--r--src/ipa/rpi/controller/rpi/denoise.h36
3 files changed, 113 insertions, 57 deletions
diff --git a/src/ipa/rpi/controller/denoise_algorithm.h b/src/ipa/rpi/controller/denoise_algorithm.h
index 52009ba9..444cbc25 100644
--- a/src/ipa/rpi/controller/denoise_algorithm.h
+++ b/src/ipa/rpi/controller/denoise_algorithm.h
@@ -6,6 +6,8 @@
*/
#pragma once
+#include <string>
+
#include "algorithm.h"
namespace RPiController {
@@ -18,6 +20,8 @@ public:
DenoiseAlgorithm(Controller *controller) : Algorithm(controller) {}
/* A Denoise algorithm must provide the following: */
virtual void setMode(DenoiseMode mode) = 0;
+ /* Some platforms may not be able to define this, so supply a default. */
+ virtual void setConfig([[maybe_unused]] std::string const &name) {}
};
} /* namespace RPiController */
diff --git a/src/ipa/rpi/controller/rpi/denoise.cpp b/src/ipa/rpi/controller/rpi/denoise.cpp
index 440ee442..154ee604 100644
--- a/src/ipa/rpi/controller/rpi/denoise.cpp
+++ b/src/ipa/rpi/controller/rpi/denoise.cpp
@@ -21,6 +21,45 @@ LOG_DEFINE_CATEGORY(RPiDenoise)
#define NAME "rpi.denoise"
+int DenoiseConfig::read(const libcamera::YamlObject &params)
+{
+ sdnEnable = params.contains("sdn");
+ if (sdnEnable) {
+ auto &sdnParams = params["sdn"];
+ sdnDeviation = sdnParams["deviation"].get<double>(3.2);
+ sdnStrength = sdnParams["strength"].get<double>(0.25);
+ sdnDeviation2 = sdnParams["deviation2"].get<double>(sdnDeviation);
+ sdnDeviationNoTdn = sdnParams["deviation_no_tdn"].get<double>(sdnDeviation);
+ sdnStrengthNoTdn = sdnParams["strength_no_tdn"].get<double>(sdnStrength);
+ sdnTdnBackoff = sdnParams["backoff"].get<double>(0.75);
+ }
+
+ cdnEnable = params.contains("cdn");
+ if (cdnEnable) {
+ auto &cdnParams = params["cdn"];
+ cdnDeviation = cdnParams["deviation"].get<double>(120);
+ cdnStrength = cdnParams["strength"].get<double>(0.2);
+ }
+
+ tdnEnable = params.contains("tdn");
+ if (tdnEnable) {
+ auto &tdnParams = params["tdn"];
+ tdnDeviation = tdnParams["deviation"].get<double>(0.5);
+ tdnThreshold = tdnParams["threshold"].get<double>(0.75);
+ } else if (sdnEnable) {
+ /*
+ * If SDN is enabled but TDN isn't, overwrite all the SDN settings
+ * with the "no TDN" versions. This makes it easier to enable or
+ * disable TDN in the tuning file without editing all the other
+ * parameters.
+ */
+ sdnDeviation = sdnDeviation2 = sdnDeviationNoTdn;
+ sdnStrength = sdnStrengthNoTdn;
+ }
+
+ return 0;
+}
+
Denoise::Denoise(Controller *controller)
: DenoiseAlgorithm(controller), mode_(DenoiseMode::ColourHighQuality)
{
@@ -33,39 +72,26 @@ char const *Denoise::name() const
int Denoise::read(const libcamera::YamlObject &params)
{
- sdnEnable_ = params.contains("sdn");
- if (sdnEnable_) {
- auto &sdnParams = params["sdn"];
- sdnDeviation_ = sdnParams["deviation"].get<double>(3.2);
- sdnStrength_ = sdnParams["strength"].get<double>(0.25);
- sdnDeviation2_ = sdnParams["deviation2"].get<double>(sdnDeviation_);
- sdnDeviationNoTdn_ = sdnParams["deviation_no_tdn"].get<double>(sdnDeviation_);
- sdnStrengthNoTdn_ = sdnParams["strength_no_tdn"].get<double>(sdnStrength_);
- sdnTdnBackoff_ = sdnParams["backoff"].get<double>(0.75);
+ if (!params.contains("normal")) {
+ configs_["normal"].read(params);
+ currentConfig_ = &configs_["normal"];
+
+ return 0;
}
- cdnEnable_ = params.contains("cdn");
- if (cdnEnable_) {
- auto &cdnParams = params["cdn"];
- cdnDeviation_ = cdnParams["deviation"].get<double>(120);
- cdnStrength_ = cdnParams["strength"].get<double>(0.2);
+ for (const auto &[key, value] : params.asDict()) {
+ if (configs_[key].read(value)) {
+ LOG(RPiDenoise, Error) << "Failed to read denoise config " << key;
+ return -EINVAL;
+ }
}
- tdnEnable_ = params.contains("tdn");
- if (tdnEnable_) {
- auto &tdnParams = params["tdn"];
- tdnDeviation_ = tdnParams["deviation"].get<double>(0.5);
- tdnThreshold_ = tdnParams["threshold"].get<double>(0.75);
- } else if (sdnEnable_) {
- /*
- * If SDN is enabled but TDN isn't, overwrite all the SDN settings
- * with the "no TDN" versions. This makes it easier to enable or
- * disable TDN in the tuning file without editing all the other
- * parameters.
- */
- sdnDeviation_ = sdnDeviation2_ = sdnDeviationNoTdn_;
- sdnStrength_ = sdnStrengthNoTdn_;
+ auto it = configs_.find("normal");
+ if (it == configs_.end()) {
+ LOG(RPiDenoise, Error) << "No normal denoise settings found";
+ return -EINVAL;
}
+ currentConfig_ = &it->second;
return 0;
}
@@ -78,9 +104,9 @@ void Denoise::switchMode([[maybe_unused]] CameraMode const &cameraMode,
[[maybe_unused]] Metadata *metadata)
{
/* A mode switch effectively resets temporal denoise and it has to start over. */
- currentSdnDeviation_ = sdnDeviationNoTdn_;
- currentSdnStrength_ = sdnStrengthNoTdn_;
- currentSdnDeviation2_ = sdnDeviationNoTdn_;
+ currentSdnDeviation_ = currentConfig_->sdnDeviationNoTdn;
+ currentSdnStrength_ = currentConfig_->sdnStrengthNoTdn;
+ currentSdnDeviation2_ = currentConfig_->sdnDeviationNoTdn;
}
void Denoise::prepare(Metadata *imageMetadata)
@@ -97,11 +123,11 @@ void Denoise::prepare(Metadata *imageMetadata)
if (mode_ == DenoiseMode::Off)
return;
- if (sdnEnable_) {
+ if (currentConfig_->sdnEnable) {
struct SdnStatus sdn;
sdn.noiseConstant = noiseStatus.noiseConstant * currentSdnDeviation_;
sdn.noiseSlope = noiseStatus.noiseSlope * currentSdnDeviation_;
- sdn.noiseConstant2 = noiseStatus.noiseConstant * sdnDeviation2_;
+ sdn.noiseConstant2 = noiseStatus.noiseConstant * currentConfig_->sdnDeviation2;
sdn.noiseSlope2 = noiseStatus.noiseSlope * currentSdnDeviation2_;
sdn.strength = currentSdnStrength_;
imageMetadata->set("sdn.status", sdn);
@@ -113,17 +139,17 @@ void Denoise::prepare(Metadata *imageMetadata)
<< " slope2 " << sdn.noiseSlope2;
/* For the next frame, we back off the SDN parameters as TDN ramps up. */
- double f = sdnTdnBackoff_;
- currentSdnDeviation_ = f * currentSdnDeviation_ + (1 - f) * sdnDeviation_;
- currentSdnStrength_ = f * currentSdnStrength_ + (1 - f) * sdnStrength_;
- currentSdnDeviation2_ = f * currentSdnDeviation2_ + (1 - f) * sdnDeviation2_;
+ double f = currentConfig_->sdnTdnBackoff;
+ currentSdnDeviation_ = f * currentSdnDeviation_ + (1 - f) * currentConfig_->sdnDeviation;
+ currentSdnStrength_ = f * currentSdnStrength_ + (1 - f) * currentConfig_->sdnStrength;
+ currentSdnDeviation2_ = f * currentSdnDeviation2_ + (1 - f) * currentConfig_->sdnDeviation2;
}
- if (tdnEnable_) {
+ if (currentConfig_->tdnEnable) {
struct TdnStatus tdn;
- tdn.noiseConstant = noiseStatus.noiseConstant * tdnDeviation_;
- tdn.noiseSlope = noiseStatus.noiseSlope * tdnDeviation_;
- tdn.threshold = tdnThreshold_;
+ tdn.noiseConstant = noiseStatus.noiseConstant * currentConfig_->tdnDeviation;
+ tdn.noiseSlope = noiseStatus.noiseSlope * currentConfig_->tdnDeviation;
+ tdn.threshold = currentConfig_->tdnThreshold;
imageMetadata->set("tdn.status", tdn);
LOG(RPiDenoise, Debug)
<< "programmed tdn threshold " << tdn.threshold
@@ -131,10 +157,10 @@ void Denoise::prepare(Metadata *imageMetadata)
<< " slope " << tdn.noiseSlope;
}
- if (cdnEnable_ && mode_ != DenoiseMode::ColourOff) {
+ if (currentConfig_->cdnEnable && mode_ != DenoiseMode::ColourOff) {
struct CdnStatus cdn;
- cdn.threshold = cdnDeviation_ * noiseStatus.noiseSlope + noiseStatus.noiseConstant;
- cdn.strength = cdnStrength_;
+ cdn.threshold = currentConfig_->cdnDeviation * noiseStatus.noiseSlope + noiseStatus.noiseConstant;
+ cdn.strength = currentConfig_->cdnStrength;
imageMetadata->set("cdn.status", cdn);
LOG(RPiDenoise, Debug)
<< "programmed cdn threshold " << cdn.threshold
@@ -148,6 +174,22 @@ void Denoise::setMode(DenoiseMode mode)
mode_ = mode;
}
+void Denoise::setConfig(std::string const &name)
+{
+ auto it = configs_.find(name);
+ if (it == configs_.end()) {
+ /*
+ * Some platforms may have no need for different denoise settings, so we only issue
+ * a warning if there clearly are several configurations.
+ */
+ if (configs_.size() > 1)
+ LOG(RPiDenoise, Warning) << "No denoise config found for " << name;
+ else
+ LOG(RPiDenoise, Debug) << "No denoise config found for " << name;
+ } else
+ currentConfig_ = &it->second;
+}
+
// Register algorithm with the system.
static Algorithm *Create(Controller *controller)
{
diff --git a/src/ipa/rpi/controller/rpi/denoise.h b/src/ipa/rpi/controller/rpi/denoise.h
index 88b37663..92ff4f93 100644
--- a/src/ipa/rpi/controller/rpi/denoise.h
+++ b/src/ipa/rpi/controller/rpi/denoise.h
@@ -6,6 +6,9 @@
*/
#pragma once
+#include <map>
+#include <string>
+
#include "algorithm.h"
#include "denoise_algorithm.h"
@@ -13,6 +16,23 @@ namespace RPiController {
// Algorithm to calculate correct denoise settings.
+struct DenoiseConfig {
+ double sdnDeviation;
+ double sdnStrength;
+ double sdnDeviation2;
+ double sdnDeviationNoTdn;
+ double sdnStrengthNoTdn;
+ double sdnTdnBackoff;
+ double cdnDeviation;
+ double cdnStrength;
+ double tdnDeviation;
+ double tdnThreshold;
+ bool tdnEnable;
+ bool sdnEnable;
+ bool cdnEnable;
+ int read(const libcamera::YamlObject &params);
+};
+
class Denoise : public DenoiseAlgorithm
{
public:
@@ -23,22 +43,12 @@ public:
void switchMode(CameraMode const &cameraMode, Metadata *metadata) override;
void prepare(Metadata *imageMetadata) override;
void setMode(DenoiseMode mode) override;
+ void setConfig(std::string const &name) override;
private:
- double sdnDeviation_;
- double sdnStrength_;
- double sdnDeviation2_;
- double sdnDeviationNoTdn_;
- double sdnStrengthNoTdn_;
- double sdnTdnBackoff_;
- double cdnDeviation_;
- double cdnStrength_;
- double tdnDeviation_;
- double tdnThreshold_;
+ std::map<std::string, DenoiseConfig> configs_;
+ DenoiseConfig *currentConfig_;
DenoiseMode mode_;
- bool tdnEnable_;
- bool sdnEnable_;
- bool cdnEnable_;
/* SDN parameters attenuate over time if TDN is running. */
double currentSdnDeviation_;