From patchwork Thu Jun 6 10:15:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 20220 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 CFA86C32CF for ; Thu, 6 Jun 2024 10:15:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0DC716546D; Thu, 6 Jun 2024 12:15:43 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="lBI5ytY+"; dkim-atps=neutral Received: from mail-ej1-x62a.google.com (mail-ej1-x62a.google.com [IPv6:2a00:1450:4864:20::62a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 50E8E6545F for ; Thu, 6 Jun 2024 12:15:34 +0200 (CEST) Received: by mail-ej1-x62a.google.com with SMTP id a640c23a62f3a-a692130eb19so75975366b.2 for ; Thu, 06 Jun 2024 03:15:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1717668933; x=1718273733; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=w6ymemoopcoht9JBOz3+IjqGaOLh0VUlpCxKvexIDPY=; b=lBI5ytY+ESZ+AxU7IhHXlFpcA0co1MKX2ghrRcrkWCsGoxbRgMgdi82rfy2v3LInoo rLPX9MMxnDZ2MFmcDZShQX9nNvlv2w0hlgtAKDQFJTouSxYNhDkWbvvHlGnhYSbpk9rl 3uJxULbDTkEKn/q27jgkXk+iwNSRjsClBmW6d3vjeXAfc1xKudyuVxZXjU0YAGsr6bdN YI0nI2/Hj3jMp6bVKSXFzmU++YEpmCWD1UELNBILzF/mRj2Ou/uxraAYoJE2pJMPtdnz 9Yb+eNtdJD4OVA9GxH6t1V6AI4A9oHIEcOOOp9WKyq5oQSulyDpPuZvv7paqd3LrKR/u ij5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1717668933; x=1718273733; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=w6ymemoopcoht9JBOz3+IjqGaOLh0VUlpCxKvexIDPY=; b=KBbYwQ3uFmcSs+agTml/SsLUi2ywleaMvXUjm6Ya5Basq5UJEPOwi1KWqZksFZOxqL HBXeIqCPOjNj+bbTznJ4qTnxYvN9lfdz61y9Zy84XIxcIflU1f0rvDeQjXozJf2qRr5N Dz0fy+EtYk/FJTWwRn9q3oy1DaqCGz3LsX2bJN/womPBL6ulo1dsVxmzHavSNiW4XcJa MeIlcMXFxIJNlSiJA+2rmvE6OCL5zOKZg6vHtd8mSQG+95dqOl/OKFOysldgyflNnLcX Ku1N0eQs5CIw8RTcKZie3AFqe9ogdU6ugblDgvvo4jADIFVFvHzP2npHNgVA/StIg9ti DOcg== X-Gm-Message-State: AOJu0Yw0F9xb5Vg5fGNl+VbGfRYUAozG1RPeDtncdJXXAYfg2im/uD00 g62lhj6UR24ubaSxBT3cQtG3d17vQ311+7LRPE5vVBVo4W5SArsKvIPK4Vv17PsxCQIyhOEdb0R k X-Google-Smtp-Source: AGHT+IEhkM/8rDYR5nhyWflyDg12IfDlp0w2oSap4FPpO3DsTPGT+cwNLHw6ZfgEZc3C3gAQl8Q6Kw== X-Received: by 2002:a17:907:9516:b0:a64:a091:91f2 with SMTP id a640c23a62f3a-a699fcdf2dfmr241608166b.37.1717668933578; Thu, 06 Jun 2024 03:15:33 -0700 (PDT) Received: from pi5-davidp.pitowers.org ([2001:4d4e:300:1f:c732:5d0a:406b:ae46]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a6c805c59a2sm75809866b.50.2024.06.06.03.15.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Jun 2024 03:15:33 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Cc: David Plowman Subject: [PATCH 6/6] utils: raspberrypi: ctt: Add a maximum gain parameter for LSC Date: Thu, 6 Jun 2024 11:15:12 +0100 Message-Id: <20240606101512.375178-7-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240606101512.375178-1-david.plowman@raspberrypi.com> References: <20240606101512.375178-1-david.plowman@raspberrypi.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" A max_gain parameter is added to the config file which we pass to the lens shading calibration. This clamps the maximum luminance gain that gets written into the tuning files so as to prevent overflows. It is particularly useful for lenses that cut off the light completely from the sensor corners, and allows usable tables to be generated for them. Signed-off-by: David Plowman --- utils/raspberrypi/ctt/ctt.py | 8 +++++--- utils/raspberrypi/ctt/ctt_alsc.py | 12 ++++++++---- utils/raspberrypi/ctt/ctt_config_example.json | 5 +++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/utils/raspberrypi/ctt/ctt.py b/utils/raspberrypi/ctt/ctt.py index 522933bd..96f1b5e6 100755 --- a/utils/raspberrypi/ctt/ctt.py +++ b/utils/raspberrypi/ctt/ctt.py @@ -269,7 +269,7 @@ class Camera: colour channel seperately, and then partially corrects for vignetting. The extent of the correction depends on the 'luminance_strength' parameter. """ - def alsc_cal(self, luminance_strength, do_alsc_colour, grid_size): + def alsc_cal(self, luminance_strength, do_alsc_colour, grid_size, max_gain=8.0): if 'rpi.alsc' in self.disable: return 1 print('\nStarting ALSC calibration') @@ -292,7 +292,7 @@ class Camera: call calibration function """ plot = "rpi.alsc" in self.plot - alsc_out = alsc_all(self, do_alsc_colour, plot, grid_size) + alsc_out = alsc_all(self, do_alsc_colour, plot, grid_size, max_gain=max_gain) cal_cr_list, cal_cb_list, luminance_lut, av_corn = alsc_out """ write output to json and finish if not do_alsc_colour @@ -705,11 +705,13 @@ def run_ctt(json_output, directory, config, log_output, json_template, grid_size alsc_d = get_config(configs, "alsc", {}, 'dict') do_alsc_colour = get_config(alsc_d, "do_alsc_colour", 1, 'bool') luminance_strength = get_config(alsc_d, "luminance_strength", 0.8, 'num') + lsc_max_gain = get_config(alsc_d, "max_gain", 8.0, 'num') blacklevel = get_config(configs, "blacklevel", -1, 'num') macbeth_d = get_config(configs, "macbeth", {}, 'dict') mac_small = get_config(macbeth_d, "small", 0, 'bool') mac_show = get_config(macbeth_d, "show", 0, 'bool') mac_config = (mac_small, mac_show) + print("Read lsc_max_gain", lsc_max_gain) if blacklevel < -1 or blacklevel >= 2**16: print('\nInvalid blacklevel, defaulted to 64') @@ -750,7 +752,7 @@ def run_ctt(json_output, directory, config, log_output, json_template, grid_size Cam.json['rpi.black_level']['black_level'] = Cam.blacklevel_16 Cam.json_remove(disable) print('\nSTARTING CALIBRATIONS') - Cam.alsc_cal(luminance_strength, do_alsc_colour, grid_size) + Cam.alsc_cal(luminance_strength, do_alsc_colour, grid_size, max_gain=lsc_max_gain) Cam.geq_cal() Cam.lux_cal() Cam.noise_cal() diff --git a/utils/raspberrypi/ctt/ctt_alsc.py b/utils/raspberrypi/ctt/ctt_alsc.py index 66ce8c14..1d94dfa5 100644 --- a/utils/raspberrypi/ctt/ctt_alsc.py +++ b/utils/raspberrypi/ctt/ctt_alsc.py @@ -13,7 +13,7 @@ from mpl_toolkits.mplot3d import Axes3D """ preform alsc calibration on a set of images """ -def alsc_all(Cam, do_alsc_colour, plot, grid_size=(16, 12)): +def alsc_all(Cam, do_alsc_colour, plot, grid_size=(16, 12), max_gain=8.0): imgs_alsc = Cam.imgs_alsc grid_w, grid_h = grid_size """ @@ -24,7 +24,7 @@ def alsc_all(Cam, do_alsc_colour, plot, grid_size=(16, 12)): list_cb = [] list_cg = [] for Img in imgs_alsc: - col, cr, cb, cg, size = alsc(Cam, Img, do_alsc_colour, plot, grid_size=grid_size) + col, cr, cb, cg, size = alsc(Cam, Img, do_alsc_colour, plot, grid_size=grid_size, max_gain=max_gain) list_col.append(col) list_cr.append(cr) list_cb.append(cb) @@ -118,7 +118,7 @@ def alsc_all(Cam, do_alsc_colour, plot, grid_size=(16, 12)): """ calculate g/r and g/b for 32x32 points arranged in a grid for a single image """ -def alsc(Cam, Img, do_alsc_colour, plot=False, grid_size=(16, 12)): +def alsc(Cam, Img, do_alsc_colour, plot=False, grid_size=(16, 12), max_gain=8.0): Cam.log += '\nProcessing image: ' + Img.name grid_w, grid_h = grid_size """ @@ -153,9 +153,12 @@ def alsc(Cam, Img, do_alsc_colour, plot=False, grid_size=(16, 12)): median blur to remove peaks and save as float 64 """ cr = cv2.medianBlur(cr, 3).astype('float64') + cr = cr/np.min(cr) # gain tables are easier for humans to read if the minimum is 1.0 cb = cv2.medianBlur(cb, 3).astype('float64') + cb = cb/np.min(cb) cg = cv2.medianBlur(cg, 3).astype('float64') cg = cg/np.min(cg) + cg = [min(v, max_gain) for v in cg.flatten()] # never exceed the max luminance gain """ debugging code showing 2D surface plot of vignetting. Quite useful for @@ -179,7 +182,7 @@ def alsc(Cam, Img, do_alsc_colour, plot=False, grid_size=(16, 12)): # print(Img.str) plt.show() - return Img.col, cr.flatten(), cb.flatten(), cg.flatten(), (w, h, dx, dy) + return Img.col, cr.flatten(), cb.flatten(), cg, (w, h, dx, dy) else: """ @@ -189,6 +192,7 @@ def alsc(Cam, Img, do_alsc_colour, plot=False, grid_size=(16, 12)): cg = np.reshape(1/g, (grid_h, grid_w)).astype('float32') cg = cv2.medianBlur(cg, 3).astype('float64') cg = cg/np.min(cg) + cg = [min(v, max_gain) for v in cg.flatten()] # never exceed the max luminance gain if plot: hf = plt.figure(figssize=(8, 8)) diff --git a/utils/raspberrypi/ctt/ctt_config_example.json b/utils/raspberrypi/ctt/ctt_config_example.json index c7f90761..1105862c 100644 --- a/utils/raspberrypi/ctt/ctt_config_example.json +++ b/utils/raspberrypi/ctt/ctt_config_example.json @@ -3,7 +3,8 @@ "plot": [], "alsc": { "do_alsc_colour": 1, - "luminance_strength": 0.5 + "luminance_strength": 0.8, + "max_gain": 8.0 }, "awb": { "greyworld": 0 @@ -13,4 +14,4 @@ "small": 0, "show": 0 } -} \ No newline at end of file +}