From patchwork Mon Nov 16 16:49:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 10438 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 915CDBE088 for ; Mon, 16 Nov 2020 16:49:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5C9C0632DC; Mon, 16 Nov 2020 17:49:38 +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="Rgg51cvT"; dkim-atps=neutral Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 706F1632E2 for ; Mon, 16 Nov 2020 17:49:33 +0100 (CET) Received: by mail-wr1-x42b.google.com with SMTP id k2so19457248wrx.2 for ; Mon, 16 Nov 2020 08:49:33 -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=Jr6QAPf1iUIZbFIQfkDfohO+vSzKEvj6JIaoOlTvUoc=; b=Rgg51cvTaovB8Dp6I780n9mCSQwyLhqIqRHL4gBJdQXWdPe/rXRiceR4U95RYXiz1R CrCicfSbPevVWq23m6uEVZHaUuZrBhOnJb/3Fx2K2rfn+rv1hbXakrwlImwOVj10W6BK SKLrOyj3X32Q8JTWtSqNZwqkYgoMnY40XnfgcopI3kap+/n+CNmdA8WPtSo8d/5ZxkI5 k10SuBJGbRvAyZu2AgOPyO8ArJT8pV6/kNE1HDP5obMHoDsINu4h5ookO+JU+l2nUwUK t2T4i6hSzT17jbMBz9MIsOiqqOyIcQEzPo/LV3vA5frsACTDvVmIQwtp9yOaVg4P3bm9 goLw== 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=Jr6QAPf1iUIZbFIQfkDfohO+vSzKEvj6JIaoOlTvUoc=; b=JxPL6RGrxjxyjDso9uvaOaRqw5anIpwMvVk19uBgK2xPbECY2Qd5LS0EPlo1SnBw/n GV1bNzO3ewNgjrS8Ym0KWbBMlI+dC6jNTf6n0b8SmpInOwNWu8gHMmQ1CKRUZ/s9a3Dv 4zXm5GlBnq0IdIfqekDLB3prVQSEz5tJ+P+nVK4k42bhLeePu42QhbcF3RMgShv/URIO Knz6o1MDA9R1eHgBHRH4swAJacEJY1Gj7fxpsRMb+7wGubsWcvgo8V/IsBPFxhwTHJQk skJJPJ2TDoVdczlVn1d+Dnw2ThBVZ0HNveddQ7xJa0n9bylkhb2hbl3GqIRFbbHepOXx jCCg== X-Gm-Message-State: AOAM531g33PAiljWdQJeksCuHQ44DeDvy+hhiUeCbb+d7LeDEtUMA25M oqtyF2Zo1qF1eiQBSchnuxkv0Fsq/qNiow== X-Google-Smtp-Source: ABdhPJwgfcxfcDUiDhnMMUwPAGuu/kiRsxNvwNoYcjiE7axU39hApTG1MhkH3TwID8F7cCHu2NTxfw== X-Received: by 2002:a5d:698c:: with SMTP id g12mr20066181wru.36.1605545372908; Mon, 16 Nov 2020 08:49:32 -0800 (PST) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id q16sm23716973wrn.13.2020.11.16.08.49.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 08:49:32 -0800 (PST) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Mon, 16 Nov 2020 16:49:17 +0000 Message-Id: <20201116164918.2055-10-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201116164918.2055-1-david.plowman@raspberrypi.com> References: <20201116164918.2055-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 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 1037f968..93b46a28 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp @@ -422,17 +422,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"; @@ -476,11 +480,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 =