From patchwork Tue Aug 12 13:38:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 24093 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 887FABDCC1 for ; Tue, 12 Aug 2025 13:39:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 224CA69249; Tue, 12 Aug 2025 15:39:02 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="GjuETK1q"; dkim-atps=neutral Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 461836921A for ; Tue, 12 Aug 2025 15:39:00 +0200 (CEST) Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-45a0dc77a15so11370905e9.2 for ; Tue, 12 Aug 2025 06:39:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1755005939; x=1755610739; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=Sij2MBaf/bKtegb0DTeP8uRGV0KedpzNM9UKXpwcmlI=; b=GjuETK1q+vMOPiF6ws3Wzkni17U5yvQMmJ6ir4Mt6vraldtL9AF5m0i0uRSQT8HmfP BtX9WEU8wsDI0ddLonPBkAiwFtXt/iPI7SWPShx8GjffnL9sJ9u8iYvnTjNckkBIhl+S 99cdteXIbeE0426AejTcMzG9Oh/6Gi+3TQVeFgoTUVYsUg9jXa/yJ0cZeouy7DtSM9yA j5bnCm/yx5swMPt5tfHhHMBTAZHH5uMmYFRN191d9LaLL4x4WCIDi6XU/I/jxUpEuSxW bElyPThkbge2XjBEduP5FVjRqCAbL9aYEaxizc1LG9gjfpA9UKSStj9vaSFc4jw7Bi4m shvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755005939; x=1755610739; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Sij2MBaf/bKtegb0DTeP8uRGV0KedpzNM9UKXpwcmlI=; b=L5/pn3Krqhv1XYUEymaXiUdVq5niihkjuLW3G8O0bHZGV8UVv0vkE/PZcju9rh2J6t T2V4VxgydEj9kbuOyoeRp94nxsx3Dp2OBAwL9KZaNPjX0vqfP3KFYqwJrb5ylitZZeOS FSmmRJritJjUIvfcjZq4RaK2Pcg2piRyUzpz8H+Gl9ISagLKeUByu98xD8LRZhmKCWus gwYfeVXgUnNDTOGIy+avwYluEYbkASwkLwyePCsGyZlvU9o88xoBJ57Yg10UvvCjVIgV K2LNDLyQ8XgcR3WnhYDduBYNn3YzcH11Q5p5UDYNoh/qf/MnGNMzBrEsAmSPUmq/BJ0f 6f7A== X-Gm-Message-State: AOJu0YwxsIfz6AyUEMjmOv0Sf34aZTCDOI3qaXupyV5hEfjNAOaXiICu OVftMyqec3VHXKlTQ0IWAUA5D+FWKdZQEEO0q5TfcAef2s/rkoAirZAfZ6pfGEOfHVxphgJRa13 99Wo9M8s= X-Gm-Gg: ASbGncsgiukdZcvU+s872pF0iOUmKzxmIzmF3qPH23/wQINLokVtfuSTMO2fK8Eo718 e3/ZqWZjv/IMJ7z4+Likv4RF2Yi21qcYkM2vAFt/vJRRFqO796pqClzE7t6nDaqyUhb12V3y+5J 6IuifGFEBvktDEkNSZ33jqjC6mqqm9IbHWgGdwVgVvm/FsjtHJV0Nal+HHhsotaLfkSEmTTgURr tEo4lV7zt+z13yg/CPpWsaRarR1WhnwdXAng9llt3OvWbTVewnVPWAlgFVDFVQSfW+FzI26H1DP 4x/nFcgcUwx9FOEiru5My7pF1URuRhXs55L3Xg9tv70JXXwjRB+aDejRVBYim9VQJmsSTOR26wq mVjnAcuGG/XkG84us57GP3UiYMv9xylLJEdVf4SwPNIVcd5mAWLH9zQ== X-Google-Smtp-Source: AGHT+IGxol9BE1BnFAfHjiJVf3mMgz2To+AvawWxf0saHscYMV6ENjt35YuyS4sp/hKk0MtLJIQZCw== X-Received: by 2002:a05:600c:45d0:b0:456:1bae:5470 with SMTP id 5b1f17b1804b1-45a10bb9684mr35996995e9.8.1755005939052; Tue, 12 Aug 2025 06:38:59 -0700 (PDT) Received: from raspberrypi.pitowers.org ([2a00:1098:3142:1f:ffc9:aff6:7f7f:893b]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-459e58553f8sm317546545e9.14.2025.08.12.06.38.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Aug 2025 06:38:58 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Cc: David Plowman Subject: [PATCH] ipa: rpi:: denoise: Implement TDN back-off for CDN deviation Date: Tue, 12 Aug 2025 14:38:56 +0100 Message-Id: <20250812133856.3981-1-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.39.5 MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The CDN (colour denoise) deviation gets gradually reduced frame by frame as TDN (temporal denoise) comes in and has more effect. CDN is more harmful to image detail than TDN, so ramping it down in favour of TDN is beneficial. The tuning file parameters are chosen so that existing tuning files don't have to be updated and will carry on working "mostly like they did" (apart from the new back-off). Signed-off-by: David Plowman Reviewed-by: Naushir Patuck Reviewed-by: Naushir Patuck --- src/ipa/rpi/controller/rpi/denoise.cpp | 22 +++++++++++++++++++--- src/ipa/rpi/controller/rpi/denoise.h | 4 +++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/ipa/rpi/controller/rpi/denoise.cpp b/src/ipa/rpi/controller/rpi/denoise.cpp index ba851658..d9bbeddd 100644 --- a/src/ipa/rpi/controller/rpi/denoise.cpp +++ b/src/ipa/rpi/controller/rpi/denoise.cpp @@ -37,7 +37,17 @@ int DenoiseConfig::read(const libcamera::YamlObject ¶ms) cdnEnable = params.contains("cdn"); if (cdnEnable) { auto &cdnParams = params["cdn"]; - cdnDeviation = cdnParams["deviation"].get(120); + cdnDeviationNoTdn = cdnParams["deviation_no_tdn"].get(150); + /* + * For backwards compatibility with existing tuning files, interpret "deviation" + * as giving the "no TDN" deviation, where present. + */ + cdnDeviationNoTdn = cdnParams["deviation"].get(cdnDeviationNoTdn); + /* + * A third the value of the no TDN deviation is about right for with-TDN, if + * the user hasn't specified otherwise. + */ + cdnDeviationWithTdn = cdnParams["deviation_with_tdn"].get(cdnDeviationNoTdn / 3); cdnStrength = cdnParams["strength"].get(0.2); } @@ -48,13 +58,14 @@ int DenoiseConfig::read(const libcamera::YamlObject ¶ms) tdnThreshold = tdnParams["threshold"].get(0.75); } else if (sdnEnable) { /* - * If SDN is enabled but TDN isn't, overwrite all the SDN settings + * If SDN is enabled but TDN isn't, overwrite all the SDN/CDN 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; + cdnDeviationWithTdn = cdnDeviationNoTdn; } return 0; @@ -107,6 +118,7 @@ void Denoise::switchMode([[maybe_unused]] CameraMode const &cameraMode, currentSdnDeviation_ = currentConfig_->sdnDeviationNoTdn; currentSdnStrength_ = currentConfig_->sdnStrengthNoTdn; currentSdnDeviation2_ = currentConfig_->sdnDeviationNoTdn; + currentCdnDeviation_ = currentConfig_->cdnDeviationNoTdn; } void Denoise::prepare(Metadata *imageMetadata) @@ -159,8 +171,12 @@ void Denoise::prepare(Metadata *imageMetadata) if (currentConfig_->cdnEnable && mode_ != DenoiseMode::ColourOff) { struct CdnStatus cdn; - cdn.threshold = currentConfig_->cdnDeviation * noiseStatus.noiseSlope + noiseStatus.noiseConstant; + cdn.threshold = currentCdnDeviation_ * noiseStatus.noiseSlope + noiseStatus.noiseConstant; cdn.strength = currentConfig_->cdnStrength; + /* For the next frame, we back off the CDN deviation as TDN ramps up. */ + double f = currentConfig_->sdnTdnBackoff; + currentCdnDeviation_ = f * currentCdnDeviation_ + (1 - f) * currentConfig_->cdnDeviationWithTdn; + imageMetadata->set("cdn.status", cdn); LOG(RPiDenoise, Debug) << "programmed cdn threshold " << cdn.threshold diff --git a/src/ipa/rpi/controller/rpi/denoise.h b/src/ipa/rpi/controller/rpi/denoise.h index 79946c97..e23a2e8f 100644 --- a/src/ipa/rpi/controller/rpi/denoise.h +++ b/src/ipa/rpi/controller/rpi/denoise.h @@ -23,7 +23,8 @@ struct DenoiseConfig { double sdnDeviationNoTdn; double sdnStrengthNoTdn; double sdnTdnBackoff; - double cdnDeviation; + double cdnDeviationNoTdn; + double cdnDeviationWithTdn; double cdnStrength; double tdnDeviation; double tdnThreshold; @@ -54,6 +55,7 @@ private: double currentSdnDeviation_; double currentSdnStrength_; double currentSdnDeviation2_; + double currentCdnDeviation_; }; } // namespace RPiController