Authenticate: one matcher run per frame, on a settled image
Two changes to the verify loop, both from measurement on the daemon. The rising edge sent events 5 and 7 from the same capture and got two verdicts back from one image -- rej rej, -11 -11, MATCH MATCH. Event 5 reaches the matcher here as well as event 7, so the second REPORT_EVENT was 250 to 300 ms of redundant work on every press, on the frame where speed matters most. Authentication now sends only event 7. Enrolment keeps event 5, where it is the sample trigger rather than a duplicate. And the frame that detects the finger is the finger landing: partial contact, and the frame that rejects most often -- across the real runs matches came at frame 3, 5 and 8 of a press, and a quick tap is one frame. So on the rising edge the daemon captures once more, about 50 ms later, before reporting, and the matcher's first look is at a settled finger. The rescan-budget experiment is reverted. At the stock budget every non-matching frame answered -11, for the enrolled finger and the wrong one alike, while matches landed exactly where they did at rescan=0. The budget relabels a non-match; it does not make the trustlet try harder. Under the press rule the two are functionally identical, and rescan=0's terminal rejection is the cleaner label.
This commit is contained in:
parent
93ab8570e0
commit
9790381e72
3 changed files with 28 additions and 11 deletions
|
|
@ -1280,12 +1280,20 @@ public:
|
||||||
out.frames++;
|
out.frames++;
|
||||||
|
|
||||||
std::string note;
|
std::string note;
|
||||||
for (ta::Event ev : tracker.Observe(finger, en::Mode::Authenticate)) {
|
bool rising = finger && !inPress;
|
||||||
if (ev == ta::Event::FingerTouched) {
|
if (rising) {
|
||||||
inPress = true; pressMatched = false; pressRejected = false;
|
inPress = true; pressMatched = false; pressRejected = false;
|
||||||
pressFrames = 0; rescans = 0; pressFid = 0;
|
pressFrames = 0; rescans = 0; pressFid = 0;
|
||||||
out.presses++;
|
out.presses++;
|
||||||
|
// The frame that detected the finger is the finger LANDING --
|
||||||
|
// partial contact, and the frame that rejects most often.
|
||||||
|
// Capture once more now that it has settled, so the image the
|
||||||
|
// matcher sees on the first report is a real one. One capture,
|
||||||
|
// ~50 ms, on the frame that decides every quick tap.
|
||||||
|
auto c2 = SendCommand(app_, ta::Cmd::CaptureImage, cap);
|
||||||
|
if (c2.invoked) { c = c2; note += " recap"; }
|
||||||
}
|
}
|
||||||
|
for (ta::Event ev : tracker.Observe(finger, en::Mode::Authenticate)) {
|
||||||
std::vector<std::byte> evbuf(ta::EventContextSize);
|
std::vector<std::byte> evbuf(ta::EventContextSize);
|
||||||
ta::BuildEventContext(evbuf, { .event = ev });
|
ta::BuildEventContext(evbuf, { .event = ev });
|
||||||
// A zero-initialised buffer cannot tell "the matcher never
|
// A zero-initialised buffer cannot tell "the matcher never
|
||||||
|
|
|
||||||
|
|
@ -88,8 +88,14 @@ export namespace fingerprintd::engine {
|
||||||
// trace. Sending event 7 on every held frame instead feeds the algorithm
|
// trace. Sending event 7 on every held frame instead feeds the algorithm
|
||||||
// near-duplicate images from a single press.
|
// near-duplicate images from a single press.
|
||||||
//
|
//
|
||||||
// Authentication does want event 7, which reaches the matcher
|
// Authentication wants event 7, which reaches the matcher unconditionally,
|
||||||
// unconditionally; event 5 only reaches it when device+0x10a8 is 1 or 2.
|
// and ONLY event 7. Event 5 reaches it too (when device+0x10a8 is 1 or 2,
|
||||||
|
// which it is here): measured on the daemon, the rising-edge frame sent
|
||||||
|
// both and got two verdicts back from one image -- `rej rej`, `-11 -11`,
|
||||||
|
// `MATCH MATCH`. Each REPORT_EVENT that runs the matcher costs 250-300 ms,
|
||||||
|
// so the second one is a third of a second of redundant work on every
|
||||||
|
// press, on the frame where speed matters most. Enrolment keeps event 5:
|
||||||
|
// there it is the sample trigger, not a duplicate.
|
||||||
class TouchTracker {
|
class TouchTracker {
|
||||||
public:
|
public:
|
||||||
// Returns the events to report for this frame, in order.
|
// Returns the events to report for this frame, in order.
|
||||||
|
|
@ -97,7 +103,7 @@ export namespace fingerprintd::engine {
|
||||||
std::vector<Event> out;
|
std::vector<Event> out;
|
||||||
bool rising = finger && !prev_;
|
bool rising = finger && !prev_;
|
||||||
bool falling = !finger && prev_;
|
bool falling = !finger && prev_;
|
||||||
if (rising)
|
if (rising && mode == Mode::Enrol)
|
||||||
out.push_back(Event::FingerTouched);
|
out.push_back(Event::FingerTouched);
|
||||||
if (finger && mode == Mode::Authenticate)
|
if (finger && mode == Mode::Authenticate)
|
||||||
out.push_back(Event::ImageReady);
|
out.push_back(Event::ImageReady);
|
||||||
|
|
|
||||||
|
|
@ -115,11 +115,14 @@ int main() {
|
||||||
auto e4 = t.Observe(false, Mode::Enrol);
|
auto e4 = t.Observe(false, Mode::Enrol);
|
||||||
Check(e4.empty(), "enrol: idle reports nothing");
|
Check(e4.empty(), "enrol: idle reports nothing");
|
||||||
|
|
||||||
// Authentication: every frame with a finger reaches the matcher.
|
// Authentication: every frame with a finger reaches the matcher, ONCE.
|
||||||
|
// Event 5 also runs the matcher here, so sending it on the rising edge
|
||||||
|
// produced two verdicts from one image and cost ~300 ms extra on the
|
||||||
|
// frame where speed matters most.
|
||||||
TouchTracker a;
|
TouchTracker a;
|
||||||
auto a1 = a.Observe(true, Mode::Authenticate);
|
auto a1 = a.Observe(true, Mode::Authenticate);
|
||||||
Check(a1.size() == 2 && a1[0] == Event::FingerTouched && a1[1] == Event::ImageReady,
|
Check(a1.size() == 1 && a1[0] == Event::ImageReady,
|
||||||
"auth: rising edge reports touched then image-ready");
|
"auth: rising edge reports image-ready only -- one matcher run, not two");
|
||||||
auto a2 = a.Observe(true, Mode::Authenticate);
|
auto a2 = a.Observe(true, Mode::Authenticate);
|
||||||
Check(a2.size() == 1 && a2[0] == Event::ImageReady, "auth: a held frame still reports image-ready");
|
Check(a2.size() == 1 && a2[0] == Event::ImageReady, "auth: a held frame still reports image-ready");
|
||||||
auto a3 = a.Observe(false, Mode::Authenticate);
|
auto a3 = a.Observe(false, Mode::Authenticate);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue