From patchwork Fri Aug 15 07:24:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 24107 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 791BDBDCC1 for ; Fri, 15 Aug 2025 07:24:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 47CCA69251; Fri, 15 Aug 2025 09:24:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="dxArgR+N"; dkim-atps=neutral Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 139F969244 for ; Fri, 15 Aug 2025 09:24:30 +0200 (CEST) Received: by mail-wr1-x434.google.com with SMTP id ffacd0b85a97d-3b9d41c1964so948654f8f.0 for ; Fri, 15 Aug 2025 00:24:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1755242669; x=1755847469; 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=Sg7PYm/EdXoa3/igcHWNrfTeF14qnakdPi7ZAGj/nOM=; b=dxArgR+NHvXvt57oPyGChiPnDVuKJbk3Ahmabrju+BT0pd71ArdhnX2u41X/1etS5n wzF+GRQFif6BXoDGzep332VdOfE1ezDdXYG1l5DDZ3tQq+5Klndj/pZpukwRPBxiWRYn nxDFMkYAvRqlcaZbkGRfl0uyv4NKvRWwBI2+zVaBeVRNxHG6NNSzRb+ou2/cRPOJDaNI Zn4bXnRKfnE6YnUb2O3HrQw5kguNjJZl+27Mrq+aPqS8eTn/QsP5AGSQcXgCa+QACgsl tra1yN4IavQga7e3U4cH+n1rSqOSy9msJeEb0hkbkBmZ7A/kbeRxOfCDqXhBjUE+viUs 4S9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755242669; x=1755847469; 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=Sg7PYm/EdXoa3/igcHWNrfTeF14qnakdPi7ZAGj/nOM=; b=uYN8S89Y2FyUgiuuQIAhYRGDN014DFOsCiKc8ZCIfH2UWfaU5dp1b4DDq0ij/t0ZHe ArIJlHxPtNZvlKszGCoLqcBTtTHOacebcIKjZ3gOFEpVscvsCUDGJrnmJIZ/GTSemLOQ xqOh4ofUT0PzyrLOaxoNKsnrLdRlLy0DVE8DB3qHFY94S51pKloDuk3AqrvkPNh96fge S4rc1q/nvrZycMCupY4RULAdsgzKfVT7bDBT8dRvNovk2ZUzIt1JddGMYTob+txq9Qb5 ewhW3KnpeX+k6YLqql/BUuI3XAxe54XO/8VPFrBL9oDk/snGQCpCwTQ5x1KZ8QrafPmE xt/w== X-Gm-Message-State: AOJu0YwfHwjrUQbTbIpXWkKcaZg6s4BhhIl9kmOQoOq3Op1ql0UviMEb RuasgrWqzhwtorSdbTQwU7uvia7ycsDglpdu3MnGxSyLl1kDNafy3z51sWv7ysJZcIQuRpKAWMT k0ShxS1I= X-Gm-Gg: ASbGncuuRCoGjNHeRvDBPsKem2T2uLNCjntY2QEKqTFsvlmTWzyL0GAOl5Tuy1vfZ69 47EHi/G3DSmrKN/GuyyzdJqUgKphYodX9r9F+pNRzyRsc6zAL+xzG5TCRXAEnEaLsYkUx+5a1y8 xOccfS+TS6msrVsNmvKIfaXsuQPvrXC0Sqm0yYDpF7i83lD85bQzdmgZ9Z5btf5PE8JXWZQS22e 0rB8V98WaMhnQdSQdim1yf5clebj8aRUw1hc5rcIrs76rWcC6qu16nkEbfgP5tyzt6lQ3VR54Oz Pbf86PZ+wfh5S2GLPTePn9MOxHoNnOhi/BzIvYh4uaWZT5+/smVuX0MSMC8O1yZ2mLs6sEeuYgA um0BkfNHqnpP2mFeiPKmxEe2M4InnMAds+75aKnrkwt3FKYc= X-Google-Smtp-Source: AGHT+IH64nv0NuROCkWXWZpZQzpGChfXvRiJJnxMB6wOn3w9K6ayGbVhqmdE0Isfd22CteldNV2y9g== X-Received: by 2002:a05:6000:290c:b0:3b7:9c79:32bb with SMTP id ffacd0b85a97d-3bb68fdc946mr653942f8f.44.1755242669204; Fri, 15 Aug 2025 00:24:29 -0700 (PDT) Received: from localhost.localdomain ([2a06:61c0:f337:0:de3:cf36:d6b2:e6cc]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3bb676c9426sm922630f8f.33.2025.08.15.00.24.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Aug 2025 00:24:28 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Cc: David Plowman , Naushir Patuck Subject: [PATCH v2] ipa: rpi:: denoise: Implement TDN back-off for CDN deviation Date: Fri, 15 Aug 2025 08:24:26 +0100 Message-Id: <20250815072426.3516-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 --- src/ipa/rpi/controller/rpi/denoise.cpp | 23 ++++++++++++++++++++--- src/ipa/rpi/controller/rpi/denoise.h | 4 +++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/ipa/rpi/controller/rpi/denoise.cpp b/src/ipa/rpi/controller/rpi/denoise.cpp index ba851658..cabe3e2a 100644 --- a/src/ipa/rpi/controller/rpi/denoise.cpp +++ b/src/ipa/rpi/controller/rpi/denoise.cpp @@ -37,7 +37,18 @@ int DenoiseConfig::read(const libcamera::YamlObject ¶ms) cdnEnable = params.contains("cdn"); if (cdnEnable) { auto &cdnParams = params["cdn"]; - cdnDeviation = cdnParams["deviation"].get(120); + /* + * For backwards compatibility with existing tuning files, interpret "deviation" + * as giving the "no TDN" deviation, where present. But "deviation_no_tdn" takes + * precedence when that's available. + */ + cdnDeviationNoTdn = cdnParams["deviation"].get(150); + cdnDeviationNoTdn = cdnParams["deviation_no_tdn"].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 +59,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 +119,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 +172,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