feat(engine): HDF5-native galleries with embedded calibration; TensorRT backends; scene detection
Gallery format switches from JSON to HDF5 exclusively (JSON read-only kept for back-compat): save_gallery always writes HDF5, and the fitted Platt-sigmoid calibration (a, b, valid, hash) is now embedded directly in the gallery file instead of a sidecar .calib_cache.json — identity_matcher reads it from the loaded gallery and writes back only when the embeddings actually changed (hash mismatch), skipping the O(n^2) refit otherwise. Also includes: TensorRT inference backend support (ort_backend.cpp, trt_backend.cpp), gemm_backend improvements, TransNetV2-based scene-boundary detection wired through frame_source/face_tracker/main, and CMake build target updates for the new sources. Bumps the KPN submodule to feature/persistent-pipeline-reuse (push_blocking backpressure, node_ptr/node_stats introspection, ObjectVariantNodeWrapper for stateful functors) — needed by the optimizer's sae_kpn Python bindings.
This commit is contained in:
@@ -335,63 +335,48 @@ inline uint64_t hash_gallery_embeddings(
|
||||
return h;
|
||||
}
|
||||
|
||||
// Calibrates the gallery, caching the fitted (a, b, valid) result on disk
|
||||
// keyed by a hash of the reference embeddings. The O(n^2) pairwise fit only
|
||||
// re-runs when the gallery's embeddings/actor assignments actually change.
|
||||
// Calibrates the gallery, reusing (cached_a, cached_b, cached_valid) if
|
||||
// cached_hash matches a fresh hash of the current embeddings/actor
|
||||
// assignments — the O(n^2) pairwise fit only re-runs when they actually
|
||||
// change. Distinct from calibrate_gallery_cached's old sidecar-JSON-file
|
||||
// design: the cache now lives in the gallery HDF5 itself (ActorGallery::
|
||||
// calib_*, see gallery_store.hpp), so this takes the previous values
|
||||
// in-memory rather than a file path. Sets `recomputed` so the caller (which
|
||||
// holds the open gallery file/struct) knows whether it needs to persist the
|
||||
// refreshed values back.
|
||||
inline GalleryCalibration calibrate_gallery_cached(
|
||||
const std::vector<Embedding>& flat_emb,
|
||||
const std::vector<int>& flat_actor,
|
||||
const std::string& cache_path)
|
||||
float cached_a,
|
||||
float cached_b,
|
||||
bool cached_valid,
|
||||
uint64_t cached_hash,
|
||||
const std::string& curve_base_path,
|
||||
bool& recomputed)
|
||||
{
|
||||
uint64_t hash = hash_gallery_embeddings(flat_emb, flat_actor);
|
||||
recomputed = false;
|
||||
|
||||
std::string base_path = cache_path;
|
||||
constexpr std::string_view kJsonExt = ".json";
|
||||
if (base_path.size() >= kJsonExt.size() &&
|
||||
base_path.compare(base_path.size() - kJsonExt.size(), kJsonExt.size(), kJsonExt) == 0)
|
||||
base_path.resize(base_path.size() - kJsonExt.size());
|
||||
|
||||
std::ifstream in(cache_path);
|
||||
if (in.is_open()) {
|
||||
try {
|
||||
nlohmann::json j;
|
||||
in >> j;
|
||||
if (j.at("hash").get<uint64_t>() == hash) {
|
||||
GalleryCalibration cal;
|
||||
cal.a = j.at("a").get<float>();
|
||||
cal.b = j.at("b").get<float>();
|
||||
cal.valid = j.at("valid").get<bool>();
|
||||
std::cerr << "[calibration] using cached calibration from "
|
||||
<< cache_path << " (a=" << cal.a << " b=" << cal.b
|
||||
<< " valid=" << cal.valid << ")\n";
|
||||
save_calibration_curve(cal, base_path);
|
||||
return cal;
|
||||
}
|
||||
std::cerr << "[calibration] cache at " << cache_path
|
||||
<< " is stale, recomputing\n";
|
||||
} catch (const std::exception&) {
|
||||
std::cerr << "[calibration] cache at " << cache_path
|
||||
<< " is unreadable, recomputing\n";
|
||||
}
|
||||
if (cached_hash != 0 && cached_hash == hash) {
|
||||
GalleryCalibration cal{cached_a, cached_b, cached_valid};
|
||||
std::cerr << "[calibration] using cached calibration from gallery"
|
||||
<< " (a=" << cal.a << " b=" << cal.b
|
||||
<< " valid=" << cal.valid << ")\n";
|
||||
if (!curve_base_path.empty()) save_calibration_curve(cal, curve_base_path);
|
||||
return cal;
|
||||
}
|
||||
if (cached_hash != 0)
|
||||
std::cerr << "[calibration] cached calibration is stale (embeddings changed), "
|
||||
"recomputing\n";
|
||||
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
GalleryCalibration cal = calibrate_gallery(flat_emb, flat_actor);
|
||||
auto t1 = std::chrono::steady_clock::now();
|
||||
double secs = std::chrono::duration<double>(t1 - t0).count();
|
||||
std::cerr << "[calibration] fit took " << secs << "s for "
|
||||
std::cerr << "[calibration] fit took "
|
||||
<< std::chrono::duration<double>(t1 - t0).count() << "s for "
|
||||
<< flat_emb.size() << " embeddings\n";
|
||||
|
||||
nlohmann::json j;
|
||||
j["hash"] = hash;
|
||||
j["a"] = cal.a;
|
||||
j["b"] = cal.b;
|
||||
j["valid"] = cal.valid;
|
||||
j["fit_secs"] = secs;
|
||||
std::ofstream out(cache_path);
|
||||
if (out.is_open()) out << j.dump(2) << "\n";
|
||||
|
||||
save_calibration_curve(cal, base_path);
|
||||
|
||||
if (!curve_base_path.empty()) save_calibration_curve(cal, curve_base_path);
|
||||
recomputed = true;
|
||||
return cal;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user