feat: identity evidence reaches the registry
Closes the link that made AR-012 inert: the tracker was maintaining registry state, but nothing called observe(), so no belief accumulated, no track was ever owned, and no presence claim could be emitted. Tracking worked and presence did not. The matcher now feeds every scored face to the registry as a calibrated posterior plus its embedding. Deliberately every scored face, not only the ones clearing prob_threshold: a run of near-misses for one actor is evidence, and discarding it would leave ownership depending on the per-frame threshold this redesign exists to stop relying on. The registry discounts for correlation and decides ownership from the accumulated posterior (AR-025). The registry is an optional dependency of the matcher. Without one it behaves exactly as before, which keeps the replay harness and the unit tests working unchanged rather than forcing every caller to construct a registry it does not need. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> TRACES: AR-012, AR-025 | SR-002
This commit is contained in:
@@ -206,6 +206,8 @@ int main(int argc, char** argv) {
|
||||
auto registry = std::make_shared<TrackRegistry>(
|
||||
reg_cfg, EvidenceDiscounter(same_person));
|
||||
|
||||
matcher_fn.set_registry(registry);
|
||||
|
||||
FaceTrackerFunc ftracker_fn{cfg, registry, same_person};
|
||||
SceneTrackerFunc tracker_fn {cfg};
|
||||
ResultSinkFunc sink_fn {cfg, done};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "gallery/gallery_store.hpp"
|
||||
#include "gallery/gallery_calibration.hpp"
|
||||
#include "gallery/track_gallery.hpp"
|
||||
#include "track_registry.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
@@ -115,6 +116,12 @@ struct IdentityMatcherFunc {
|
||||
/// mean different things. See `same_person_probability`.
|
||||
const GalleryCalibration& calibration() const { return cal_; }
|
||||
|
||||
/// TRACES: AR-012, AR-025 | SR-002
|
||||
/// Where per-frame identity evidence reaches the registry. Optional: with no
|
||||
/// registry attached the matcher behaves exactly as before, which keeps the
|
||||
/// replay harness and the unit tests working unchanged.
|
||||
void set_registry(std::shared_ptr<TrackRegistry> r) { registry_ = std::move(r); }
|
||||
|
||||
// Runtime setter — lets a persistent pipeline be reused across a threshold sweep
|
||||
// without rebuilding the (expensive, gallery-resident) matcher. The gallery,
|
||||
// calibration and GPU sim-engine stay put; only the accept threshold changes.
|
||||
@@ -232,6 +239,19 @@ struct IdentityMatcherFunc {
|
||||
// face (annex already folded in above); the track's diversity buffer
|
||||
// keeps the gallery-far views and promotes them once the track is
|
||||
// confirmed. No-op unless --expand-gallery is set.
|
||||
// TRACES: AR-012, AR-025 | SR-002
|
||||
// Every scored face is evidence, not only the accepted ones: a run of
|
||||
// near-misses for one actor is itself informative, and discarding it
|
||||
// would make ownership depend on a per-frame threshold the redesign
|
||||
// exists to stop relying on. The registry discounts for correlation
|
||||
// and decides ownership from the accumulated posterior (AR-025).
|
||||
if (registry_ && best_actor >= 0 && tf.track_ids[fi] >= 0) {
|
||||
const float p = cal_.valid
|
||||
? cal_.probability(best_s, log_prior_odds_)
|
||||
: std::max(0.f, best_s);
|
||||
registry_->observe(tf.track_ids[fi], best_actor, p, tf.embeddings[fi]);
|
||||
}
|
||||
|
||||
track_gallery_.observe(tf.track_ids[fi], tf.embeddings[fi],
|
||||
best_actor, best_s, accept, tf.crops[fi]);
|
||||
|
||||
@@ -255,4 +275,5 @@ private:
|
||||
|
||||
std::unique_ptr<ISimilarityEngine> sim_engine_;
|
||||
TrackGallery track_gallery_;
|
||||
std::shared_ptr<TrackRegistry> registry_;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user