如果新的raw id和旧的sid特别像,优先不创建,可能是track错误
This commit is contained in:
@@ -124,7 +124,7 @@ register_keys:
|
||||
target_reid_gap_threshold: 0.10
|
||||
target_reid_min_crop_area: 2000.0
|
||||
target_reid_max_crop_aspect_ratio: 0.90
|
||||
target_reid_feature_update_interval: 5
|
||||
target_reid_feature_update_interval: 3
|
||||
target_reid_lost_timeout_frames: 150
|
||||
target_reid_gallery_size: 8
|
||||
target_reid_input_height: 256
|
||||
|
||||
@@ -748,6 +748,7 @@ std::vector<int> TargetObservationProcessor::bind_and_update_tracks(
|
||||
// Only brand-new unmatched rows go through the consecutive-hit gate in
|
||||
// Phase 4 before receiving a fresh stable_id.
|
||||
bool reid_recovery_attempted = false;
|
||||
std::vector<bool> suppress_new_sid(static_cast<size_t>(row_count), false);
|
||||
for (int i = 0; i < row_count; ++i) {
|
||||
if (stable_ids[static_cast<size_t>(i)] >= 0) {
|
||||
continue;
|
||||
@@ -855,6 +856,60 @@ std::vector<int> TargetObservationProcessor::bind_and_update_tracks(
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 3.75: duplicate suppression. If an unbound row strongly matches
|
||||
// an already claimed stable_id, treat it as a duplicate ByteTrack split
|
||||
// of an existing person instead of allocating a new stable_id.
|
||||
//
|
||||
// Typical failure mode:
|
||||
// raw 1 -> sid0, raw 2 -> sid1, then ByteTrack temporarily emits raw 3
|
||||
// for the same person as sid0 while raw 1 is still alive.
|
||||
// Without this guard, raw 3 would stay unbound, accumulate pending hits,
|
||||
// and eventually get promoted to a brand-new sid2 even though its ReID
|
||||
// is almost identical to sid0. Here we suppress that path.
|
||||
for (int i = 0; i < row_count; ++i) {
|
||||
if (stable_ids[static_cast<size_t>(i)] >= 0) {
|
||||
continue;
|
||||
}
|
||||
const ReIDFeature& feature = features_by_row[static_cast<size_t>(i)];
|
||||
if (feature.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int best_sid = -1;
|
||||
float top1 = -1.0f;
|
||||
float top2 = -1.0f;
|
||||
for (const auto& kv : tracks_) {
|
||||
if (kv.second.gallery.empty()) {
|
||||
continue;
|
||||
}
|
||||
const float sim = kv.second.gallery.best_similarity(feature);
|
||||
if (sim > top1) {
|
||||
top2 = top1;
|
||||
top1 = sim;
|
||||
best_sid = kv.first;
|
||||
} else if (sim > top2) {
|
||||
top2 = sim;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_sid < 0) {
|
||||
continue;
|
||||
}
|
||||
if (!taken_sids.count(best_sid)) {
|
||||
continue; // free sids are handled by Phase 3 ReID recovery
|
||||
}
|
||||
if (top1 < config_.reid_match_threshold) {
|
||||
continue;
|
||||
}
|
||||
if (top2 >= 0.0f && (top1 - top2) < config_.reid_gap_threshold) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const int raw_id = static_cast<int>(tracks(i, 4));
|
||||
pending_raw_ids_.erase(raw_id);
|
||||
suppress_new_sid[static_cast<size_t>(i)] = true;
|
||||
}
|
||||
|
||||
// Phase 4: allocate a fresh stable_id for rows that still have no match.
|
||||
// Apply the confirmed-track gate: a ByteTrack raw_id must show up for
|
||||
// `reid_confirm_hits_before_allocate` consecutive frames before getting
|
||||
@@ -866,6 +921,9 @@ std::vector<int> TargetObservationProcessor::bind_and_update_tracks(
|
||||
if (stable_ids[static_cast<size_t>(i)] >= 0) {
|
||||
continue;
|
||||
}
|
||||
if (suppress_new_sid[static_cast<size_t>(i)]) {
|
||||
continue;
|
||||
}
|
||||
const int raw_id = static_cast<int>(tracks(i, 4));
|
||||
auto [pit, inserted] = pending_raw_ids_.try_emplace(raw_id);
|
||||
PendingRaw& pending = pit->second;
|
||||
|
||||
Reference in New Issue
Block a user