diff --git a/plugins/ai_face_recog/ai_face_recog_node.cpp b/plugins/ai_face_recog/ai_face_recog_node.cpp index 7767b08..c40c7d0 100644 --- a/plugins/ai_face_recog/ai_face_recog_node.cpp +++ b/plugins/ai_face_recog/ai_face_recog_node.cpp @@ -63,16 +63,32 @@ inline bool IsPersonDetection(const Detection& det, int person_class_id) { return det.cls_id == person_class_id; } -int AssociateFaceToPersonTrack(const Rect& face_bbox, const std::vector& dets, int person_class_id) { +struct FaceTrackAssociationDiag { + int total_dets = 0; + int person_dets = 0; + int tracked_person_dets = 0; + int containing_tracked_person_dets = 0; + int best_track_id = -1; + float best_overlap = -1.0f; +}; + +int AssociateFaceToPersonTrack(const Rect& face_bbox, const std::vector& dets, int person_class_id, + FaceTrackAssociationDiag* diag = nullptr) { const float center_x = face_bbox.x + face_bbox.w * 0.5f; const float center_y = face_bbox.y + face_bbox.h * 0.5f; + if (diag) *diag = FaceTrackAssociationDiag{}; + if (diag) diag->total_dets = static_cast(dets.size()); + int best_track_id = -1; float best_overlap = -1.0f; for (const auto& det : dets) { + if (diag && IsPersonDetection(det, person_class_id)) ++diag->person_dets; if (!IsPersonDetection(det, person_class_id)) continue; if (det.track_id < 0) continue; + if (diag) ++diag->tracked_person_dets; if (!ContainsPoint(det.bbox, center_x, center_y)) continue; + if (diag) ++diag->containing_tracked_person_dets; const float overlap = IntersectionArea(face_bbox, det.bbox); if (overlap > best_overlap) { @@ -81,9 +97,34 @@ int AssociateFaceToPersonTrack(const Rect& face_bbox, const std::vectorbest_track_id = best_track_id; + diag->best_overlap = best_overlap; + } return best_track_id; } +std::string BuildFaceTrackAssociationDiagLine(const std::string& node_id, uint64_t frame_id, const Rect& face_bbox, + int person_class_id, const FaceTrackAssociationDiag& diag) { + std::ostringstream oss; + oss << "[ai_face_recog] track_assoc" + << " id=" << node_id + << " frame=" << frame_id + << " person_class_id=" << person_class_id + << " face_bbox=(" << static_cast(std::lround(face_bbox.x)) + << "," << static_cast(std::lround(face_bbox.y)) + << "," << static_cast(std::lround(face_bbox.w)) + << "," << static_cast(std::lround(face_bbox.h)) + << ")" + << " dets=" << diag.total_dets + << " person_dets=" << diag.person_dets + << " tracked_person_dets=" << diag.tracked_person_dets + << " containing_tracked_person_dets=" << diag.containing_tracked_person_dets + << " best_track_id=" << diag.best_track_id + << " best_overlap=" << std::fixed << std::setprecision(1) << diag.best_overlap; + return oss.str(); +} + struct GalleryEntry { int person_id = -1; std::string name; @@ -924,6 +965,7 @@ private: for (int i = 0; i < limit; ++i) { const FaceDetItem& face = frame->face_det->faces[static_cast(i)]; + FaceTrackAssociationDiag assoc_diag; face_buf_.resize(static_cast(model_w_) * static_cast(model_h_) * 3); if (cfg->align && face.has_landmarks && model_w_ == 112 && model_h_ == 112) { @@ -1001,7 +1043,7 @@ private: FaceRecogItem item; item.bbox = face.bbox; item.person_track_id = frame->det - ? AssociateFaceToPersonTrack(face.bbox, frame->det->items, cfg->person_class_id) + ? AssociateFaceToPersonTrack(face.bbox, frame->det->items, cfg->person_class_id, &assoc_diag) : -1; item.has_landmarks = face.has_landmarks; item.landmarks = face.landmarks; @@ -1016,6 +1058,11 @@ private: if (cfg->emit_embedding) item.embedding = emb; rr.items.push_back(std::move(item)); + + if (cfg->debug.enabled && cfg->debug.log_matches) { + LogInfo(BuildFaceTrackAssociationDiagLine(id_, frame->frame_id, face.bbox, + cfg->person_class_id, assoc_diag)); + } } if (sync_src) frame->SyncEnd();