From patchwork Fri Jun 7 07:59:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 20228 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 A80C6BD87C for ; Fri, 7 Jun 2024 07:59:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5A2256545A; Fri, 7 Jun 2024 09:59:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="jWepHlG1"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 476FA633DD for ; Fri, 7 Jun 2024 09:59:23 +0200 (CEST) Received: from neptunite.hamster-moth.ts.net (h175-177-049-156.catv02.itscom.jp [175.177.49.156]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B3D70C67; Fri, 7 Jun 2024 09:59:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1717747153; bh=xHCSuh8UP54e7dYCC0ly154u8tT7c3ko6QciQc3a6LY=; h=From:To:Cc:Subject:Date:From; b=jWepHlG1p2AFyyPaRRfg3/FSGeRCb4P5rVrAons9V93ZD38qaZCCzS4SdiQ0KDbRJ ILv03sm4exEBaqYS/9NJxGltSzr4YP+ZZCRAD1jh5COxHl7xhDWQoq/m+PVEhSES19 chtKOzjYpfjJMzvKEs5NrvipqbOowmTk55wN+UcU= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder Subject: [PATCH v3] ipa: libipa: Change constraint Y target to piecewise linear function Date: Fri, 7 Jun 2024 16:59:14 +0900 Message-Id: <20240607075914.2655019-1-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 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" Change the constraint luminance target from a scalar value to a piecewise linear function that needs to be sampled by the estimated lux value. Signed-off-by: Paul Elder --- This patch depends on v5 of "ipa:: Move Pwl from Raspberry Pi" Changes in v3: - use new PointF that's a typedef of Vector Changes in v2: - s/FPoint/PointF/ - construct default Pwl with *two* points so that it actually constructs properly --- src/ipa/libipa/agc_mean_luminance.cpp | 15 +++++++++------ src/ipa/libipa/agc_mean_luminance.h | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp index 10c16850d..575143610 100644 --- a/src/ipa/libipa/agc_mean_luminance.cpp +++ b/src/ipa/libipa/agc_mean_luminance.cpp @@ -168,8 +168,10 @@ void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id) AgcConstraint::Bound bound = static_cast(idx); double qLo = content["qLo"].get().value_or(0.98); double qHi = content["qHi"].get().value_or(1.0); - double yTarget = - content["yTarget"].getList().value_or(std::vector{ 0.5 }).at(0); + Pwl yTarget; + int ret = yTarget.readYaml(content["yTarget"]); + if (ret < 0) + yTarget = Pwl({ Pwl::PointF({ 0, 0.5 }), Pwl::PointF({ 1000, 0.5 }) }); AgcConstraint constraint = { bound, qLo, qHi, yTarget }; @@ -221,7 +223,7 @@ int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData) AgcConstraint::Bound::lower, 0.98, 1.0, - 0.5 + Pwl({ Pwl::PointF({ 0, 0.5 }), Pwl::PointF({ 1000, 0.5 }) }) }; constraintModes_[controls::ConstraintNormal].insert( @@ -471,16 +473,17 @@ double AgcMeanLuminance::estimateInitialGain(double lux) const * \param[in] constraintModeIndex The index of the constraint to adhere to * \param[in] hist A histogram over which to calculate inter-quantile means * \param[in] gain The gain to clamp + * \param[in] lux The lux value at which to sample the constraint luminance target pwl * * \return The gain clamped within the constraint bounds */ double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex, const Histogram &hist, - double gain) + double gain, double lux) { std::vector &constraints = constraintModes_[constraintModeIndex]; for (const AgcConstraint &constraint : constraints) { - double newGain = constraint.yTarget * hist.bins() / + double newGain = constraint.yTarget.eval(constraint.yTarget.domain().clamp(lux)) * hist.bins() / hist.interQuantileMean(constraint.qLo, constraint.qHi); if (constraint.bound == AgcConstraint::Bound::lower && @@ -559,7 +562,7 @@ AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex, exposureModeHelpers_.at(exposureModeIndex); double gain = estimateInitialGain(lux); - gain = constraintClampGain(constraintModeIndex, yHist, gain); + gain = constraintClampGain(constraintModeIndex, yHist, gain, lux); /* * We don't check whether we're already close to the target, because diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h index 6ec2a0dc9..d43f673dd 100644 --- a/src/ipa/libipa/agc_mean_luminance.h +++ b/src/ipa/libipa/agc_mean_luminance.h @@ -38,7 +38,7 @@ public: Bound bound; double qLo; double qHi; - double yTarget; + Pwl yTarget; }; int parseTuningData(const YamlObject &tuningData); @@ -80,7 +80,7 @@ private: double estimateInitialGain(double lux) const; double constraintClampGain(uint32_t constraintModeIndex, const Histogram &hist, - double gain); + double gain, double lux); utils::Duration filterExposure(utils::Duration exposureValue); uint64_t frameCount_;