From patchwork Mon Aug 5 12:05:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20771 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 01F8AC323E for ; Mon, 5 Aug 2024 12:05:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A66CF63385; Mon, 5 Aug 2024 14:05:55 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="A9s/S2EV"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AB43D6195D for ; Mon, 5 Aug 2024 14:05:52 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:30ff:e7b4:349c:44ce]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5EC20581; Mon, 5 Aug 2024 14:05:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1722859501; bh=SWD+JJG6iwx8L2d9BHWiU2/XvE5aNdYH6jstXTLijeE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=A9s/S2EVVe4l3hE/JntiZmY2vBzzz/90/21ooPGOKn+ngxu4oHbtxKIFityFMdlYA P5Fr8vXAe2DJ/AeYZt+wD4s5EEjw2KnBE/GHGCFPBRZl6BxB5eL0gF23t6V4s7/wsw 34KEYZh9KP+6qd1IZ6KhXJbPECH0t7orvnAWgUQg= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: David Plowman , Stefan Klug Subject: [PATCH v1 1/6] libcamera: controls: Update the ColourTemperature control to be writable Date: Mon, 5 Aug 2024 14:05:02 +0200 Message-ID: <20240805120522.1613342-2-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240805120522.1613342-1-stefan.klug@ideasonboard.com> References: <20240805120522.1613342-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" For manual control it is helpful to be able to specify a fixed colour temperature. It also provides a easy way to apply the temperature specific CCMs and colour gains that are contained in the tuning files. Document this and update the control dependencies. Signed-off-by: Stefan Klug --- src/libcamera/control_ids_core.yaml | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml index 9d413a94e0ee..90a52bccaa98 100644 --- a/src/libcamera/control_ids_core.yaml +++ b/src/libcamera/control_ids_core.yaml @@ -252,9 +252,12 @@ controls: - AwbEnable: type: bool description: | - Enable or disable the AWB. + Enable or disable the AWB. Disabling AWB stops updates to the + ColourGains and to the ColourCorrectionMatrix. + \sa ColourCorrectionMatrix \sa ColourGains + \sa ColourTemperature # AwbMode needs further attention: # - Auto-generate max enum value. @@ -309,13 +312,24 @@ controls: disabled. \sa AwbEnable + \sa ColourTemperature size: [2] - ColourTemperature: type: int32_t - description: Report the current estimate of the colour temperature, in - kelvin, for this frame. The ColourTemperature control can only be - returned in metadata. + description: | + Report the current estimate of the colour temperature, in kelvin, for + this frame. An implementation may also allow this control to be set when + AWB is disabled. In that case ColourGains and the ColourCorrectionMatrix + get set accordingly. If either ColourGains or ColourCorrectionMatrix are + specified at the same time, they takes precedence. + + Note that the metadata always contains the measured value, even when the + value was set manually. + + \sa AwbEnable + \sa ColourCorrectionMatrix + \sa ColourGains - Saturation: type: float @@ -365,6 +379,8 @@ controls: transformation. The 3x3 matrix is stored in conventional reading order in an array of 9 floating point values. + \sa AwbEnable + \sa ColourTemperature size: [3,3] - ScalerCrop: From patchwork Mon Aug 5 12:05:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20772 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 22B68C323E for ; Mon, 5 Aug 2024 12:05:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7BFC26337E; Mon, 5 Aug 2024 14:05:56 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="kmz14V2x"; 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 E461D63369 for ; Mon, 5 Aug 2024 14:05:54 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:30ff:e7b4:349c:44ce]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8D1E4AB5; Mon, 5 Aug 2024 14:05:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1722859503; bh=CSJ1LfBzo/4SQKazTF2Sb4F+6RnatDuscp4MOkWhoGc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kmz14V2x6633sOls2ePeUhCxPLULXlStMM4YPgLAwrvFj45OrjmCLVxBNq1hBWLFb qGNm+Mi2Qb+OczOlCPq0BAbdPUn1IdvX1jVnNgUFICx8n1u1Rmm5Ojb6KZXUj7JZly OShx7U30KSn0ga1zvrwz+8kW+pQiWM1TaSU4Ei4k= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: David Plowman , Stefan Klug Subject: [PATCH v1 2/6] ipa: rkisp1: awb: Load white balance gains from tuning file Date: Mon, 5 Aug 2024 14:05:03 +0200 Message-ID: <20240805120522.1613342-3-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240805120522.1613342-1-stefan.klug@ideasonboard.com> References: <20240805120522.1613342-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" For the implementation of a manual colour temperature setting, it is necessary to read predefined colour gains per colour temperature from the tuning file. Implement this in a backwards compatible way. If no gains are contained in the tuning file, loading just continues as before. Signed-off-by: Stefan Klug Reviewed-by: Kieran Bingham --- src/ipa/rkisp1/algorithms/awb.cpp | 18 ++++++++++++++++++ src/ipa/rkisp1/algorithms/awb.h | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index 4ccafd48dedd..957d24fe3425 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -39,6 +39,24 @@ Awb::Awb() { } +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int Awb::init(IPAContext &context, const YamlObject &tuningData) +{ + MatrixInterpolator gains; + int ret = gains.readYaml(tuningData["gains"], "ct", "gains"); + if (ret < 0) + LOG(RkISP1Awb, Warning) + << "Failed to parse 'gains' " + << "parameter from tuning file; " + << "rgb gains will not be set based on colour temperature"; + else + gains_ = gains; + + return 0; +} + /** * \copydoc libcamera::ipa::Algorithm::configure */ diff --git a/src/ipa/rkisp1/algorithms/awb.h b/src/ipa/rkisp1/algorithms/awb.h index 06c92896e2dc..a010e6d1cb3c 100644 --- a/src/ipa/rkisp1/algorithms/awb.h +++ b/src/ipa/rkisp1/algorithms/awb.h @@ -7,6 +7,10 @@ #pragma once +#include + +#include "libipa/matrix_interpolator.h" + #include "algorithm.h" namespace libcamera { @@ -19,6 +23,7 @@ public: Awb(); ~Awb() = default; + int init(IPAContext &context, const YamlObject &tuningData) override; int configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override; void queueRequest(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, @@ -34,6 +39,7 @@ public: private: uint32_t estimateCCT(double red, double green, double blue); + std::optional> gains_; bool rgbMode_; }; From patchwork Mon Aug 5 12:05:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20773 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 5B7AAC323E for ; Mon, 5 Aug 2024 12:06:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EB36F6338D; Mon, 5 Aug 2024 14:06:02 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="MqhwLb+h"; 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 02F0E63385 for ; Mon, 5 Aug 2024 14:05:58 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:30ff:e7b4:349c:44ce]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 64BDAA06; Mon, 5 Aug 2024 14:05:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1722859506; bh=V3A4n7vjPjDVEBZ5c5kzhoo4IFWKvuJR1cka4FNwiuE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MqhwLb+hIgV6IjGGw7JPFe8M2w7NJbMGmNVwSpZoYSum9Y6IpUQAFLcggsbGH3/PW LwdezwJ2VAGqli17u67uLZN9W2KFr1015M9CfT5VnojKf314Afa684tzc87mpkPHaq 8/r6+HzmucPWYDnDrb1Z1CSnp9O88W8LYGYKtijo= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: David Plowman , Stefan Klug Subject: [PATCH v1 3/6] ipa: rkisp1: awb: Implement ColourTemperature control Date: Mon, 5 Aug 2024 14:05:04 +0200 Message-ID: <20240805120522.1613342-4-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240805120522.1613342-1-stefan.klug@ideasonboard.com> References: <20240805120522.1613342-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. As the colour temperature reported in the metadata is always based on the measurements, we don't have to touch that. Note that in the automatic case, the colour gains are still based on the gray world model and the ones from the tuning file get ignored. Signed-off-by: Stefan Klug --- src/ipa/rkisp1/algorithms/awb.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index 957d24fe3425..d482eda5b541 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -31,6 +31,10 @@ namespace ipa::rkisp1::algorithms { LOG_DEFINE_CATEGORY(RkISP1Awb) +constexpr int32_t kMinColourTemperature = 2500; +constexpr int32_t kMaxColourTemperature = 10000; +constexpr int32_t kDefaultColourTemperature = 6500; + /* Minimum mean value below which AWB can't operate. */ constexpr double kMeanMinThreshold = 2.0; @@ -44,6 +48,11 @@ Awb::Awb() */ int Awb::init(IPAContext &context, const YamlObject &tuningData) { + auto &cmap = context.ctrlMap; + cmap[&controls::ColourTemperature] = ControlInfo(kMinColourTemperature, + kMaxColourTemperature, + kDefaultColourTemperature); + MatrixInterpolator gains; int ret = gains.readYaml(tuningData["gains"], "ct", "gains"); if (ret < 0) @@ -113,6 +122,17 @@ void Awb::queueRequest(IPAContext &context, << ", blue: " << awb.gains.manual.blue; } + const auto &colourTemperature = controls.get(controls::ColourTemperature); + if (colourTemperature && !awb.autoEnabled && gains_ && !colourGains) { + Matrix gains = gains_->get(*colourTemperature); + awb.gains.manual.red = gains[0][0]; + awb.gains.manual.blue = gains[1][0]; + + LOG(RkISP1Awb, Debug) + << "Set colour gains to red: " << awb.gains.manual.red + << ", blue: " << awb.gains.manual.blue; + } + frameContext.awb.autoEnabled = awb.autoEnabled; if (!awb.autoEnabled) { From patchwork Mon Aug 5 12:05:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20774 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 DE90CC324E for ; Mon, 5 Aug 2024 12:06:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 524076338B; Mon, 5 Aug 2024 14:06:04 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="E2oy8LU7"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3BA376337E for ; Mon, 5 Aug 2024 14:06:00 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:30ff:e7b4:349c:44ce]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E1FB0581; Mon, 5 Aug 2024 14:05:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1722859509; bh=E2cADFmxSRuhQqszjDsqeaWRefHJym6wwsDovjUMKUk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=E2oy8LU7VCZDVI21W/LkrAsXqrftG0aV/7CnLca84uBmuJmBRuW0MO1+aaoZQTOFq EkR0hpK+FxMaqpwQ6yM/vCWUobpIjL/ORE/xBlrGjM2R6uYLqs9M6cxeULIMjC5986 2/xajwHzYUkct2+sgJCU7N9UIp04ryC4olicokSg= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: David Plowman , Stefan Klug Subject: [PATCH v1 4/6] libtuning: Modify ctt_awb.awb() so that it can run in our context Date: Mon, 5 Aug 2024 14:05:05 +0200 Message-ID: <20240805120522.1613342-5-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240805120522.1613342-1-stefan.klug@ideasonboard.com> References: <20240805120522.1613342-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" Modify the awb function that was copied from the Raspberry Pi tuning scripts in a way that it can easily be called from the libtuning code. In essence the logging was replaced by calls to a python logger and the need for the Cam object was removed by providing a list of images to the function. Signed-off-by: Stefan Klug Reviewed-by: Kieran Bingham --- utils/tuning/libtuning/ctt_awb.py | 55 ++++++++++++++++--------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/utils/tuning/libtuning/ctt_awb.py b/utils/tuning/libtuning/ctt_awb.py index abf22321a0ea..73a1bc1a840c 100644 --- a/utils/tuning/libtuning/ctt_awb.py +++ b/utils/tuning/libtuning/ctt_awb.py @@ -4,6 +4,8 @@ # # camera tuning tool for AWB +import logging + import matplotlib.pyplot as plt from bisect import bisect_left from scipy.optimize import fmin @@ -11,12 +13,12 @@ import numpy as np from .image import Image +logger = logging.getLogger(__name__) """ obtain piecewise linear approximation for colour curve """ -def awb(Cam, cal_cr_list, cal_cb_list, plot): - imgs = Cam.imgs +def awb(imgs, cal_cr_list, cal_cb_list, plot): """ condense alsc calibration tables into one dictionary """ @@ -39,7 +41,7 @@ def awb(Cam, cal_cr_list, cal_cb_list, plot): rb_raw = [] rbs_hat = [] for Img in imgs: - Cam.log += '\nProcessing '+Img.name + logger.info(f'Processing {Img.name}') """ get greyscale patches with alsc applied if alsc enabled. Note: if alsc is disabled then colour_cals will be set to None and the @@ -51,7 +53,7 @@ def awb(Cam, cal_cr_list, cal_cb_list, plot): """ r_g = np.mean(r_patchs/g_patchs) b_g = np.mean(b_patchs/g_patchs) - Cam.log += '\n r : {:.4f} b : {:.4f}'.format(r_g, b_g) + logger.info(' r : {:.4f} b : {:.4f}'.format(r_g, b_g)) """ The curve tends to be better behaved in so-called hatspace. R, B, G represent the individual channels. The colour curve is plotted in @@ -74,12 +76,11 @@ def awb(Cam, cal_cr_list, cal_cb_list, plot): """ r_g_hat = r_g/(1+r_g+b_g) b_g_hat = b_g/(1+r_g+b_g) - Cam.log += '\n r_hat : {:.4f} b_hat : {:.4f}'.format(r_g_hat, b_g_hat) - rbs_hat.append((r_g_hat, b_g_hat, Img.col)) + logger.info('\n r_hat : {:.4f} b_hat : {:.4f}'.format(r_g_hat, b_g_hat)) + rbs_hat.append((r_g_hat, b_g_hat, Img.color)) rb_raw.append((r_g, b_g)) - Cam.log += '\n' - Cam.log += '\nFinished processing images' + logger.info('Finished processing images') """ sort all lits simultaneously by r_hat """ @@ -95,7 +96,7 @@ def awb(Cam, cal_cr_list, cal_cb_list, plot): fit quadratic fit to r_g hat and b_g_hat """ a, b, c = np.polyfit(rbs_hat[0], rbs_hat[1], 2) - Cam.log += '\nFit quadratic curve in hatspace' + logger.info('Fit quadratic curve in hatspace') """ the algorithm now approximates the shortest distance from each point to the curve in dehatspace. Since the fit is done in hatspace, it is easier to @@ -151,14 +152,14 @@ def awb(Cam, cal_cr_list, cal_cb_list, plot): if (x+y) > (rr+bb): dist *= -1 dists.append(dist) - Cam.log += '\nFound closest point on fit line to each point in dehatspace' + logger.info('Found closest point on fit line to each point in dehatspace') """ calculate wiggle factors in awb. 10% added since this is an upper bound """ transverse_neg = - np.min(dists) * 1.1 transverse_pos = np.max(dists) * 1.1 - Cam.log += '\nTransverse pos : {:.5f}'.format(transverse_pos) - Cam.log += '\nTransverse neg : {:.5f}'.format(transverse_neg) + logger.info('Transverse pos : {:.5f}'.format(transverse_pos)) + logger.info('Transverse neg : {:.5f}'.format(transverse_neg)) """ set minimum transverse wiggles to 0.1 . Wiggle factors dictate how far off of the curve the algorithm searches. 0.1 @@ -167,10 +168,10 @@ def awb(Cam, cal_cr_list, cal_cb_list, plot): """ if transverse_pos < 0.01: transverse_pos = 0.01 - Cam.log += '\nForced transverse pos to 0.01' + logger.info('Forced transverse pos to 0.01') if transverse_neg < 0.01: transverse_neg = 0.01 - Cam.log += '\nForced transverse neg to 0.01' + logger.info('Forced transverse neg to 0.01') """ generate new b_hat values at each r_hat according to fit @@ -202,25 +203,25 @@ def awb(Cam, cal_cr_list, cal_cb_list, plot): i = len(c_fit) - 1 while i > 0: if c_fit[i] > c_fit[i-1]: - Cam.log += '\nColour temperature increase found\n' - Cam.log += '{} K at r = {} to '.format(c_fit[i-1], r_fit[i-1]) - Cam.log += '{} K at r = {}'.format(c_fit[i], r_fit[i]) + logger.info('Colour temperature increase found') + logger.info('{} K at r = {} to '.format(c_fit[i-1], r_fit[i-1])) + logger.info('{} K at r = {}'.format(c_fit[i], r_fit[i])) """ if colour temperature increases then discard point furthest from the transformed fit (dehatspace) """ error_1 = abs(dists[i-1]) error_2 = abs(dists[i]) - Cam.log += '\nDistances from fit:\n' - Cam.log += '{} K : {:.5f} , '.format(c_fit[i], error_1) - Cam.log += '{} K : {:.5f}'.format(c_fit[i-1], error_2) + logger.info('Distances from fit:') + logger.info('{} K : {:.5f} , '.format(c_fit[i], error_1)) + logger.info('{} K : {:.5f}'.format(c_fit[i-1], error_2)) """ find bad index note that in python false = 0 and true = 1 """ bad = i - (error_1 < error_2) - Cam.log += '\nPoint at {} K deleted as '.format(c_fit[bad]) - Cam.log += 'it is furthest from fit' + logger.info('Point at {} K deleted as '.format(c_fit[bad])) + logger.info('it is furthest from fit') """ delete bad point """ @@ -239,12 +240,12 @@ def awb(Cam, cal_cr_list, cal_cb_list, plot): return formatted ct curve, ordered by increasing colour temperature """ ct_curve = list(np.array(list(zip(b_fit, r_fit, c_fit))).flatten())[::-1] - Cam.log += '\nFinal CT curve:' + logger.info('Final CT curve:') for i in range(len(ct_curve)//3): j = 3*i - Cam.log += '\n ct: {} '.format(ct_curve[j]) - Cam.log += ' r: {} '.format(ct_curve[j+1]) - Cam.log += ' b: {} '.format(ct_curve[j+2]) + logger.info(' ct: {} '.format(ct_curve[j])) + logger.info(' r: {} '.format(ct_curve[j+1])) + logger.info(' b: {} '.format(ct_curve[j+2])) """ plotting code for debug @@ -303,7 +304,7 @@ def get_alsc_patches(Img, colour_cals, grey=True): """ if grey: cen_coords = Img.cen_coords[3::4] - col = Img.col + col = Img.color patches = [np.array(Img.patches[i]) for i in Img.order] r_patchs = patches[0][3::4] - Img.blacklevel_16 b_patchs = patches[3][3::4] - Img.blacklevel_16 From patchwork Mon Aug 5 12:05:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20775 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 3FD09C323E for ; Mon, 5 Aug 2024 12:06:08 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CCB51633B2; Mon, 5 Aug 2024 14:06:07 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="rpKo5ZMh"; 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 AD1D963385 for ; Mon, 5 Aug 2024 14:06:02 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:30ff:e7b4:349c:44ce]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5F568581; Mon, 5 Aug 2024 14:05:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1722859511; bh=drQpmeEVWshewFVgjah1K/r7bqB8fNREwlf4SYeJN8g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rpKo5ZMhuDj4HbgZp0MV2kCvDMLrZu1MXHq2OYE8ceIcTEOhsbbBQ0uxCPZ39wcMg bfzjF7GCa+jipo4gR2789zIFXbi5h1um9snDbZBsL+5Nu0e+sOd58kK83JXgv+lsOq jOUirQHhIfctrJeC/s28y46KcVIK605U7aXNAFmg= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: David Plowman , Stefan Klug Subject: [PATCH v1 5/6] libtuning: Add initial AWB module Date: Mon, 5 Aug 2024 14:05:06 +0200 Message-ID: <20240805120522.1613342-6-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240805120522.1613342-1-stefan.klug@ideasonboard.com> References: <20240805120522.1613342-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" This AWB modules uses the awb function from Raspberry Pi to calculate the needed white balance gains per colour temperature. It stores these gains in the tuning file. Currently they are only used for the manual colour temperature control. It is likely that they will be used with more complex awb algorithms. Signed-off-by: Stefan Klug Reviewed-by: Kieran Bingham --- .../tuning/libtuning/modules/awb/__init__.py | 6 +++ utils/tuning/libtuning/modules/awb/awb.py | 42 +++++++++++++++++++ utils/tuning/libtuning/modules/awb/rkisp1.py | 27 ++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 utils/tuning/libtuning/modules/awb/__init__.py create mode 100644 utils/tuning/libtuning/modules/awb/awb.py create mode 100644 utils/tuning/libtuning/modules/awb/rkisp1.py diff --git a/utils/tuning/libtuning/modules/awb/__init__.py b/utils/tuning/libtuning/modules/awb/__init__.py new file mode 100644 index 000000000000..2d67f10cfc4f --- /dev/null +++ b/utils/tuning/libtuning/modules/awb/__init__.py @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2024, Ideas On Board + +from libtuning.modules.awb.awb import AWB +from libtuning.modules.awb.rkisp1 import AWBRkISP1 diff --git a/utils/tuning/libtuning/modules/awb/awb.py b/utils/tuning/libtuning/modules/awb/awb.py new file mode 100644 index 000000000000..5680a44fd3e3 --- /dev/null +++ b/utils/tuning/libtuning/modules/awb/awb.py @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2024, Ideas On Board + +import logging + +from ..module import Module + +from libtuning.ctt_awb import awb +import numpy as np + +logger = logging.getLogger(__name__) + + +class AWB(Module): + type = 'awb' + hr_name = 'AWB (Base)' + out_name = 'GenericAWB' + + def __init__(self, *, + debug: list): + super().__init__() + + self.debug = debug + + def do_calculation(self, images): + logger.info('Starting AWB calculation') + + imgs = [img for img in images if img.macbeth is not None] + + gains, _, _ = awb(imgs, None, None, False) + gains = np.array(gains) + gains = gains.reshape(-1, 3) + + res = [] + for v in gains: + res.append({ + 'ct': int(v[0]), + 'gains': [float(1.0 / v[1]), float(1.0 / v[2])] + }) + + return res diff --git a/utils/tuning/libtuning/modules/awb/rkisp1.py b/utils/tuning/libtuning/modules/awb/rkisp1.py new file mode 100644 index 000000000000..e3ddeb50c9a1 --- /dev/null +++ b/utils/tuning/libtuning/modules/awb/rkisp1.py @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2024, Ideas On Board +# +# AWB module for tuning rkisp1 + +from .awb import AWB + +import libtuning as lt + + +class AWBRkISP1(AWB): + hr_name = 'AWB (RkISP1)' + out_name = 'Awb' + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + def validate_config(self, config: dict) -> bool: + return True + + def process(self, config: dict, images: list, outputs: dict) -> dict: + output = {} + + output['gains'] = self.do_calculation(images) + + return output From patchwork Mon Aug 5 12:05:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 20776 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 AFB41C323E for ; Mon, 5 Aug 2024 12:06:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0F27C63393; Mon, 5 Aug 2024 14:06:10 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="gLTlfbeF"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 68C806338D for ; Mon, 5 Aug 2024 14:06:05 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:30ff:e7b4:349c:44ce]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1AEFAA06; Mon, 5 Aug 2024 14:05:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1722859514; bh=JsPxZJzNsXIeSqpBOS2R+347SqpjTnI0DU228sQQxZE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gLTlfbeFK/lr4ITyKbT7GDI8j2FbFPSu/fNOLmvwW9tlR1d7diMESF00ESITHpbYG 6cDs4MjbvE+1GQl4N34E32O5RsAG4kKyOlp+PkWNWoz3Zzqusb6QWOSp0WJFhXSI9K 3xMI998tDrOipj4P7SKWS8iPjjy93/8JtnktvwKk= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: David Plowman , Stefan Klug Subject: [PATCH v1 6/6] utils: tuning: rkisp1: Replace static AWB with new AWB module Date: Mon, 5 Aug 2024 14:05:07 +0200 Message-ID: <20240805120522.1613342-7-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240805120522.1613342-1-stefan.klug@ideasonboard.com> References: <20240805120522.1613342-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 rkisp1 tuner used a static module to insert the AWB algorithm into the tuning file. Replace that with the new AWB module. Signed-off-by: Stefan Klug Reviewed-by: Kieran Bingham --- utils/tuning/rkisp1.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/tuning/rkisp1.py b/utils/tuning/rkisp1.py index f5c42a61d15e..9f40fd8bd63b 100755 --- a/utils/tuning/rkisp1.py +++ b/utils/tuning/rkisp1.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later # # Copyright (C) 2022, Paul Elder +# Copyright (C) 2024, Ideas On Board # # Tuning script for rkisp1 @@ -14,13 +15,14 @@ from libtuning.parsers import YamlParser from libtuning.generators import YamlOutput from libtuning.modules.lsc import LSCRkISP1 from libtuning.modules.agc import AGCRkISP1 +from libtuning.modules.awb import AWBRkISP1 from libtuning.modules.ccm import CCMRkISP1 from libtuning.modules.static import StaticModule coloredlogs.install(level=logging.INFO, fmt='%(name)s %(levelname)s %(message)s') agc = AGCRkISP1(debug=[lt.Debug.Plot]) -awb = StaticModule('Awb') +awb = AWBRkISP1(debug=[lt.Debug.Plot]) blc = StaticModule('BlackLevelCorrection') ccm = CCMRkISP1(debug=[lt.Debug.Plot]) color_processing = StaticModule('ColorProcessing')