summaryrefslogtreecommitdiff
path: root/src/ipa/rpi/controller/rpi/denoise.cpp
diff options
context:
space:
mode:
authorDavid Plowman <david.plowman@raspberrypi.com>2023-10-13 08:48:39 +0100
committerKieran Bingham <kieran.bingham@ideasonboard.com>2023-10-18 11:01:23 +0100
commitac232470fb3182b8b6299a7d317681d540561d5d (patch)
treee341e1034bf38b840638788524b141e93d607cfd /src/ipa/rpi/controller/rpi/denoise.cpp
parent0ff20bf8c1d21ffbb3694b67756abc59151132cf (diff)
ipa: rpi: denoise: Support different denoise configurations
Some use cases may require stronger, or different, denosie settings to others. For example, the way frames are accumulated during single exposure HDR means that we may want stronger denoise. This commit adds such support for different configurations that can be defined in the tuning file. Older tuning files, or files where there is only a single configuration, load only the "normal" denoise configuration. Signed-off-by: David Plowman <david.plowman@raspberrypi.com> Reviewed-by: Naushir Patuck <naush@raspberrypi.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'src/ipa/rpi/controller/rpi/denoise.cpp')
-rw-r--r--src/ipa/rpi/controller/rpi/denoise.cpp130
1 files changed, 86 insertions, 44 deletions
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)
{