From patchwork Mon Nov 23 07:38:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 10468 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 B3A31BE08A for ; Mon, 23 Nov 2020 07:38:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7F84463350; Mon, 23 Nov 2020 08:38:41 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="An+uLqiS"; dkim-atps=neutral Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E49FA63325 for ; Mon, 23 Nov 2020 08:38:38 +0100 (CET) Received: by mail-wm1-x330.google.com with SMTP id 1so16283273wme.3 for ; Sun, 22 Nov 2020 23:38:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=l1N2pr2q7Z9XN1viacAoQlqJnMssJB536U10h0wxdDc=; b=An+uLqiSKQdfdI4+8GOqCNCmhOyLbgyEca5cI2bYXtL81O2+t9BROT/sjehgRc/Xs3 dyLwwjq3sMLb2ygxbnZLByIrf1j5DVkcVw1Jcu+4MoF5GYfa1zRtA75EaD59SHz8kioc cgoyDIrx5WXr8ybaeo+9KGegL3a0tmf0/twiMLvB8bed41ok6319qiR+tvGlgLQiCVbe A6ZlgRo4S3PucC96Tnoi0pqnxrmktNVpdUwEN8+C9g5xtUgASpbj4MNjQ0aY/7PPBnS2 ifuy7h0QPlyr8DkZ6QSz/qiGXekaJvG3wd973+kQdIqZvQXPXf1EMPeFutdam4LHCU0q PH+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=l1N2pr2q7Z9XN1viacAoQlqJnMssJB536U10h0wxdDc=; b=YbcrQt1VBvxd18rqFe2BqS8UJyulh4ocpHhiLM1vpniJl9XHyKDoVRSxpse/Ymh18j Gqu4k3yIseL8Sp+pYiFQkBEU1BMNlxgPUKg+VsSedFSK/5tjqgjuyWnUKwAdA6RCSXQ5 fTLzH/d8jVzT1IHWgzJmtK40DePyogGUM8CFkUDmUAxDdKMvWOZ8RoUMoy+QA61HQt/F GVFESYpcEgCYxD1Mw2BzBeOixYxusbrk3VSIPPOuK3xrbWXJklEt8QvgLFxKPTNIFB6N cUJBiKcRyDb7sk/ZuRvhPusFgHTf3cQPXWJoj9ViLe/H+qmbKaMViq/etg+3G4IiV8OG Y3vQ== X-Gm-Message-State: AOAM531qKTqRjD8z6n66OYFg4canIhJKCxqd4qz92ms/1jH5rcL7uzaN AsOCirR+6m4F93C6jswTYYqSffsCEPgN97ZC X-Google-Smtp-Source: ABdhPJx33csanBlg9ffLf0RgrNGI103mdr3LYwjBrjAhocfMD5DMPeiRUz71xxE80lDl57306OiYtQ== X-Received: by 2002:a1c:3c4:: with SMTP id 187mr8148864wmd.143.1606117118355; Sun, 22 Nov 2020 23:38:38 -0800 (PST) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id h15sm17841822wrw.15.2020.11.22.23.38.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 22 Nov 2020 23:38:37 -0800 (PST) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Mon, 23 Nov 2020 07:38:03 +0000 Message-Id: <20201123073804.3125-10-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201123073804.3125-1-david.plowman@raspberrypi.com> References: <20201123073804.3125-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 09/10] libcamera: src: ipa: raspberrypi: agc: Improve gain update calculation for partly saturated images 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" When parts of an image saturate then the image brightness no longer increases linearly with increased exposure/gain. Having calculated a linear gain value it's better then to try it, allowing for saturating regions, and if necessary increase the gain some more. We repeat this several times. Signed-off-by: David Plowman Reviewed-by: Naushir Patuck --- src/ipa/raspberrypi/controller/rpi/agc.cpp | 34 +++++++++++++++------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp index d7d37055..37806055 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp @@ -419,17 +419,21 @@ void Agc::fetchAwbStatus(Metadata *image_metadata) } static double compute_initial_Y(bcm2835_isp_stats *stats, AwbStatus const &awb, - double weights[]) + double weights[], double gain) { bcm2835_isp_stats_region *regions = stats->agc_stats; // Note how the calculation below means that equal weights give you // "average" metering (i.e. all pixels equally important). double R_sum = 0, G_sum = 0, B_sum = 0, pixel_sum = 0; for (int i = 0; i < AGC_STATS_SIZE; i++) { - R_sum += regions[i].r_sum * weights[i]; - G_sum += regions[i].g_sum * weights[i]; - B_sum += regions[i].b_sum * weights[i]; - pixel_sum += regions[i].counted * weights[i]; + double counted = regions[i].counted; + double r_sum = std::min(regions[i].r_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted); + double g_sum = std::min(regions[i].g_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted); + double b_sum = std::min(regions[i].b_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted); + R_sum += r_sum * weights[i]; + G_sum += g_sum * weights[i]; + B_sum += b_sum * weights[i]; + pixel_sum += counted * weights[i]; } if (pixel_sum == 0.0) { LOG(RPiAgc, Warning) << "compute_initial_Y: pixel_sum is zero"; @@ -473,11 +477,21 @@ void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *image_metadata, target_Y = config_.Y_target.Eval(config_.Y_target.Domain().Clip(lux.lux)); target_Y = std::min(EV_GAIN_Y_TARGET_LIMIT, target_Y * ev_gain); - double initial_Y = compute_initial_Y(statistics, awb_, - metering_mode_->weights); - gain = std::min(10.0, target_Y / (initial_Y + .001)); - LOG(RPiAgc, Debug) << "Initially Y " << initial_Y << " target " << target_Y - << " gives gain " << gain; + + // Do this calculation a few times as brightness increase can be + // non-linear when there are saturated regions. + gain = 1.0; + for (int i = 0; i < 8; i++) { + double initial_Y = compute_initial_Y(statistics, awb_, + metering_mode_->weights, gain); + double extra_gain = std::min(10.0, target_Y / (initial_Y + .001)); + gain *= extra_gain; + LOG(RPiAgc, Debug) << "Initial Y " << initial_Y << " target " << target_Y + << " gives gain " << gain; + if (extra_gain < 1.01) // close enough + break; + } + for (auto &c : *constraint_mode_) { double new_target_Y; double new_gain =