From patchwork Wed Mar 19 16:01:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 22976 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 7709BC3301 for ; Wed, 19 Mar 2025 16:02:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2FD2268950; Wed, 19 Mar 2025 17:02:01 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="onr8Soyr"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 43B4E68950 for ; Wed, 19 Mar 2025 17:01:58 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:760:e5ca:4814:99c7]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 622501E6; Wed, 19 Mar 2025 17:00:15 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1742400015; bh=38PgVpMLCn1rU1JAGX96dX81FNIUPDUJkZQfAyhJte4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=onr8Soyr8yOTnDsNMvPDeHm/KFZ0CrYDfbuzIemNZSCxDrNjrV9p6XBfRySJX+P8Z kJaUWDSn1TR4HKc0HPq9pP+tyN5o+49qb+zZUUEumX24P85NhQJdWNWlTjGrQskn9U R+Hfggtdd/XxVyg8tMY0OaDJH2zeE35nZ20Ihnec= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 1/2] ipa: rkisp1: agc: Fix metering modes Date: Wed, 19 Mar 2025 17:01:36 +0100 Message-ID: <20250319160146.61751-2-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250319160146.61751-1-stefan.klug@ideasonboard.com> References: <20250319160146.61751-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" The weights for a given metering mode are applied to the histogram data inside the histogram statistics block. The AE statistics do not contain any weights. Therefore the weights are honored when AgcMeanLuminance calculates the upper or lower constraints, but ignored in the calculation of the frame luminance. Fix that by manually applying the weights in the luminance calculation. Fixes: 4c5152843a2a ("ipa: rkisp1: Derive rkisp1::algorithms::Agc from AgcMeanLuminance") Signed-off-by: Stefan Klug --- src/ipa/rkisp1/algorithms/agc.cpp | 13 ++++++++++--- src/ipa/rkisp1/algorithms/agc.h | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 5a3ba0131cf1..101cad5d0893 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -439,15 +439,20 @@ void Agc::fillMetadata(IPAContext &context, IPAFrameContext &frameContext, */ double Agc::estimateLuminance(double gain) const { + ASSERT(expMeans_.size() == weights_.size()); double ySum = 0.0; + double wSum = 0.0; /* Sum the averages, saturated to 255. */ - for (uint8_t expMean : expMeans_) - ySum += std::min(expMean * gain, 255.0); + for (unsigned i = 0; i < expMeans_.size(); i++) { + double w = weights_[i]; + ySum += std::min(expMeans_[i] * gain, 255.0) * w; + wSum += w; + } /* \todo Weight with the AWB gains */ - return ySum / expMeans_.size() / 255; + return ySum / wSum / 255; } /** @@ -515,6 +520,8 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, Histogram hist({ params->hist.hist_bins, context.hw->numHistogramBins }, [](uint32_t x) { return x >> 4; }); expMeans_ = { params->ae.exp_mean, context.hw->numAeCells }; + std::vector &modeWeights = meteringModes_.at(frameContext.agc.meteringMode); + weights_ = { modeWeights.data(), modeWeights.size() }; /* * Set the AGC limits using the fixed exposure time and/or gain in diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h index 62bcde999fe3..7867eed9c4e3 100644 --- a/src/ipa/rkisp1/algorithms/agc.h +++ b/src/ipa/rkisp1/algorithms/agc.h @@ -55,6 +55,7 @@ private: utils::Duration frameDuration); Span expMeans_; + Span weights_; std::map> meteringModes_; }; From patchwork Wed Mar 19 16:01:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 22977 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 016D8C3301 for ; Wed, 19 Mar 2025 16:02:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AE32F68958; Wed, 19 Mar 2025 17:02:03 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="eAYYQqsB"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8432E68957 for ; Wed, 19 Mar 2025 17:02:01 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:760:e5ca:4814:99c7]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7D90A1E6; Wed, 19 Mar 2025 17:00:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1742400018; bh=zI9Pe25uJV1j/LfDiMV2CdRrM3azElPfJy5XZBXWzvI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eAYYQqsB68XI9+DU6hDrSaKAvVPbW28VutuNr06Xcxpa0VwAxvlXN6OncYKxeHZYO HWelCRJAvcC7/fN1HB+eSw4bHiMBw/kjgJwSN/NC5tUXEHJcAbs2obvxLAulyo3zvV MLMMEgiX+DcSLUv6PVvCEeJ/HUR/Ve88SqWHht/Y= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 2/2] ipa: rkisp1: agc: Set measurement window to full frame Date: Wed, 19 Mar 2025 17:01:37 +0100 Message-ID: <20250319160146.61751-3-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250319160146.61751-1-stefan.klug@ideasonboard.com> References: <20250319160146.61751-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" With the availability of metering modes and the corresponding weights, there is a flexible way of defining the area that gets taken into account when AEGC is calculated. There is no need to reduce that window to an arbitrary region anymore. If need arises we can make this parameter user configurable or add a control for it. Signed-off-by: Stefan Klug --- src/ipa/rkisp1/algorithms/agc.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 101cad5d0893..b3ac9400b74f 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -193,14 +193,10 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) context.activeState.agc.minFrameDuration = std::chrono::microseconds(frameDurationLimits.min().get()); context.activeState.agc.maxFrameDuration = std::chrono::microseconds(frameDurationLimits.max().get()); - /* - * Define the measurement window for AGC as a centered rectangle - * covering 3/4 of the image width and height. - */ - context.configuration.agc.measureWindow.h_offs = configInfo.outputSize.width / 8; - context.configuration.agc.measureWindow.v_offs = configInfo.outputSize.height / 8; - context.configuration.agc.measureWindow.h_size = 3 * configInfo.outputSize.width / 4; - context.configuration.agc.measureWindow.v_size = 3 * configInfo.outputSize.height / 4; + context.configuration.agc.measureWindow.h_offs = 0; + context.configuration.agc.measureWindow.v_offs = 0; + context.configuration.agc.measureWindow.h_size = configInfo.outputSize.width; + context.configuration.agc.measureWindow.v_size = configInfo.outputSize.height; setLimits(context.configuration.sensor.minExposureTime, context.configuration.sensor.maxExposureTime,