fp6-img/aports/temp/libcamera/0014-libcamera-software_isp-af-Re-baseline-the-scene-refe.patch

114 lines
4.3 KiB
Diff
Raw Normal View History

From b99ba09cd463cbfbb6530a82c9e2702bfd0bb29a Mon Sep 17 00:00:00 2001
From: Jorijn van der Graaf <jorijnvdgraaf@catcrafts.net>
Date: Mon, 17 Aug 2026 02:18:32 +0200
Subject: [PATCH] libcamera: software_isp: af: Re-baseline the scene reference
after a sweep
Measured on the FP6 with the DW9784: a sweep converged on 38% with a
recorded maximum sharpness of 4848088, and two stats frames later the
metric at that same position read 1995445 - a 59% drop with the lens
parked and the scene unchanged. The sweep maximum was measured under
whatever exposure and gain the AGC happened to be using several hundred
milliseconds earlier, so comparing the settled scene against it fires
the focus-loss detector immediately and the lens sweeps forever.
Take the reference from the first measurement after the lens has
settled, and require the scene to look different for four consecutive
stats frames before re-focusing, so that a single AGC excursion does not
count as the scene changing.
Signed-off-by: Jorijn van der Graaf <jorijnvdgraaf@catcrafts.net>
---
src/ipa/simple/algorithms/af.cpp | 37 ++++++++++++++++++++++++++------
src/ipa/simple/ipa_context.h | 4 ++++
2 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/src/ipa/simple/algorithms/af.cpp b/src/ipa/simple/algorithms/af.cpp
index 00148ce1b..6c9510389 100644
--- a/src/ipa/simple/algorithms/af.cpp
+++ b/src/ipa/simple/algorithms/af.cpp
@@ -34,6 +34,8 @@ constexpr double kFineStepMin = 1.0;
constexpr uint32_t kSettleSkipLong = 3;
/* Relative sharpness change that makes a settled scene worth re-focusing. */
constexpr double kFocusLossThreshold = 0.3;
+/* Consecutive stats frames that change must persist for before re-focusing. */
+constexpr uint32_t kFocusLossFrames = 4;
/*
* Focus continuously by default: applications that know nothing about AF never
* send an AfMode or an AfTrigger, and they are the ones this exists for.
@@ -140,6 +142,8 @@ void Af::restart(IPAContext &context)
focus.stop = 100;
focus.step = kCoarseStep;
focus.skip = kSettleSkipLong;
+ focus.settled = false;
+ focus.lossCount = 0;
context.activeState.knobs.focus_pos = 0;
context.activeState.knobs.focus_sweep = true;
LOG(IPASoftAutoFocus, Info) << "Starting focus sweep";
@@ -165,13 +169,34 @@ void Af::step(IPAContext &context, double &focus_pos, uint64_t sharp, bool &swee
if (context.activeState.knobs.af_mode != controls::AfModeContinuous)
return;
- if (utils::abs_diff(sharp, focus.sharpness_max) >
+ /*
+ * Take the reference the scene is compared against here, at
+ * the settled position, rather than reusing the maximum found
+ * during the sweep: that maximum was measured under whatever
+ * exposure and gain the AGC happened to be using at the time.
+ */
+ if (!focus.settled) {
+ focus.sharpness_max = sharp;
+ focus.lossCount = 0;
+ focus.settled = true;
+ LOG(IPASoftAutoFocus, Debug)
+ << "Settled sharpness reference " << sharp;
+ return;
+ }
+
+ if (utils::abs_diff(sharp, focus.sharpness_max) <=
focus.sharpness_max * kFocusLossThreshold) {
- LOG(IPASoftAutoFocus, Info)
- << "Focus lost: " << sharp << " vs "
- << focus.sharpness_max;
- restart(context);
+ focus.lossCount = 0;
+ return;
}
+
+ if (++focus.lossCount < kFocusLossFrames)
+ return;
+
+ LOG(IPASoftAutoFocus, Info)
+ << "Focus lost: " << sharp << " vs "
+ << focus.sharpness_max;
+ restart(context);
return;
}
@@ -204,10 +229,10 @@ void Af::step(IPAContext &context, double &focus_pos, uint64_t sharp, bool &swee
sweep = false;
focus_pos = focus.focus_max_pos;
+ focus.settled = false;
LOG(IPASoftAutoFocus, Info)
<< "Sweep end. Best focus: " << focus.focus_max_pos
<< " after " << steps_ << " frames";
- /* sharpness_max is kept to detect the scene changing later on. */
}
void Af::process(IPAContext &context,
diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
index 4c594cd29..36a28256b 100644
--- a/src/ipa/simple/ipa_context.h
+++ b/src/ipa/simple/ipa_context.h
@@ -41,6 +41,10 @@ struct IPASessionConfiguration {
double start, stop, step;
/* Stats frames to ignore while the lens settles */
uint32_t skip;
+ /* Set once the post-sweep sharpness reference has been taken */
+ bool settled;
+ /* Consecutive stats frames the scene has looked different */
+ uint32_t lossCount;
} focus;
};