From patchwork Thu Dec 19 17:57:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 22411 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 07F65C3272 for ; Thu, 19 Dec 2024 17:57:48 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 67D1E68486; Thu, 19 Dec 2024 18:57:47 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="AijzNkXE"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 21BBE68481 for ; Thu, 19 Dec 2024 18:57:42 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:783:85f9:c998:cb11]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4C63EAD8; Thu, 19 Dec 2024 18:57:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1734631023; bh=EFIMPL9bJiAOcv8nKEqT0wrUgTgwwYUg41VwflN086s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AijzNkXEhYSvLD4nd/hT7g9FCN3k5Y71lDan2a7NSu5iZoyhKatnFVpp1L06bZBBy Vh/QxoUo26u7BFh/OYdjAS+fMmwLIBIHO2EdMMTnNS/vYKFKUrgtNbeWu0YBZ+BPmY 9QjvhcZNYZKm9mzfiYmjS+mMnntmBJdWsKlDj1Pk= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Paul Elder , Kieran Bingham Subject: [PATCH v6 3/9] ipa: rkisp1: awb: Implement ColourTemperature control Date: Thu, 19 Dec 2024 18:57:20 +0100 Message-ID: <20241219175729.293782-4-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241219175729.293782-1-stefan.klug@ideasonboard.com> References: <20241219175729.293782-1-stefan.klug@ideasonboard.com> 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" There are many use-cases (tuning-validation, working in static environments) where a manual ColourTemperature control is helpful. Implement that by interpolating and applying the white balance gains from the tuning file according to the requested colour temperature. If colour gains are provided on the same request, they take precedence. Store the colour temperature used for a given frame in the frame context and report that in metadata. Note that in the automatic case, the colour gains are still based on the gray world model and the CT curve from the tuning file get ignored. Signed-off-by: Stefan Klug Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- Changes in v6: - Updated commit message - Moved retrieval of controls to the place where needed - Output the colour temperature applied to a frame in metadata --- src/ipa/rkisp1/algorithms/awb.cpp | 51 +++++++++++++++++++++++-------- src/ipa/rkisp1/ipa_context.h | 1 + 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index e23f67a96edf..cffaa06a22c1 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -33,6 +33,10 @@ namespace ipa::rkisp1::algorithms { LOG_DEFINE_CATEGORY(RkISP1Awb) +constexpr int32_t kMinColourTemperature = 2500; +constexpr int32_t kMaxColourTemperature = 10000; +constexpr int32_t kDefaultColourTemperature = 5000; + /* Minimum mean value below which AWB can't operate. */ constexpr double kMeanMinThreshold = 2.0; @@ -44,8 +48,13 @@ Awb::Awb() /** * \copydoc libcamera::ipa::Algorithm::init */ -int Awb::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData) +int Awb::init(IPAContext &context, const YamlObject &tuningData) { + auto &cmap = context.ctrlMap; + cmap[&controls::ColourTemperature] = ControlInfo(kMinColourTemperature, + kMaxColourTemperature, + kDefaultColourTemperature); + Interpolator> gainCurve; int ret = gainCurve.readYaml(tuningData["colourGains"], "ct", "gains"); if (ret < 0) @@ -68,6 +77,7 @@ int Awb::configure(IPAContext &context, context.activeState.awb.gains.manual = RGB{ 1.0 }; context.activeState.awb.gains.automatic = RGB{ 1.0 }; context.activeState.awb.autoEnabled = true; + context.activeState.awb.temperatureK = kDefaultColourTemperature; /* * Define the measurement window for AWB as a centered rectangle @@ -101,19 +111,37 @@ void Awb::queueRequest(IPAContext &context, << (*awbEnable ? "Enabling" : "Disabling") << " AWB"; } + frameContext.awb.autoEnabled = awb.autoEnabled; + + if (awb.autoEnabled) + return; + const auto &colourGains = controls.get(controls::ColourGains); - if (colourGains && !awb.autoEnabled) { + const auto &colourTemperature = controls.get(controls::ColourTemperature); + bool update = false; + if (colourGains) { awb.gains.manual.r() = (*colourGains)[0]; awb.gains.manual.b() = (*colourGains)[1]; + /* + * \todo: Colour temperature reported in metadata is now + * incorrect, as we can't deduce the temperature from the gains. + * This will be fixed with the bayes AWB algorithm. + */ + update = true; + } else if (colourTemperature && colourGainCurve_) { + const auto &gains = colourGainCurve_->getInterpolated(*colourTemperature); + awb.gains.manual.r() = gains[0]; + awb.gains.manual.b() = gains[1]; + awb.temperatureK = *colourTemperature; + update = true; + } + if (update) LOG(RkISP1Awb, Debug) << "Set colour gains to " << awb.gains.manual; - } - frameContext.awb.autoEnabled = awb.autoEnabled; - - if (!awb.autoEnabled) - frameContext.awb.gains = awb.gains.manual; + frameContext.awb.gains = awb.gains.manual; + frameContext.awb.temperatureK = awb.temperatureK; } /** @@ -126,8 +154,10 @@ void Awb::prepare(IPAContext &context, const uint32_t frame, * This is the latest time we can read the active state. This is the * most up-to-date automatic values we can read. */ - if (frameContext.awb.autoEnabled) + if (frameContext.awb.autoEnabled) { frameContext.awb.gains = context.activeState.awb.gains.automatic; + frameContext.awb.temperatureK = context.activeState.awb.temperatureK; + } auto gainConfig = params->block(); gainConfig.setEnabled(true); @@ -206,7 +236,7 @@ void Awb::process(IPAContext &context, static_cast(frameContext.awb.gains.r()), static_cast(frameContext.awb.gains.b()) }); - metadata.set(controls::ColourTemperature, activeState.awb.temperatureK); + metadata.set(controls::ColourTemperature, frameContext.awb.temperatureK); if (!stats || !(stats->meas_type & RKISP1_CIF_ISP_STAT_AWB)) { LOG(RkISP1Awb, Error) << "AWB data is missing in statistics"; @@ -281,9 +311,6 @@ void Awb::process(IPAContext &context, activeState.awb.temperatureK = estimateCCT(rgbMeans); - /* Metadata shall contain the up to date measurement */ - metadata.set(controls::ColourTemperature, activeState.awb.temperatureK); - /* * Estimate the red and blue gains to apply in a grey world. The green * gain is hardcoded to 1.0. Avoid divisions by zero by clamping the diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index deb8c196f1b8..4b50015beee8 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -135,6 +135,7 @@ struct IPAFrameContext : public FrameContext { struct { RGB gains; bool autoEnabled; + unsigned int temperatureK; } awb; struct {