64 lines
4.2 KiB
Python
64 lines
4.2 KiB
Python
import importlib.util
|
|
import pathlib
|
|
import sys
|
|
import textwrap
|
|
import unittest
|
|
|
|
|
|
REPO_ROOT = pathlib.Path(__file__).resolve().parents[1]
|
|
SCRIPT_PATH = REPO_ROOT / "tools" / "analyze_face_recog_log.py"
|
|
|
|
|
|
def load_module():
|
|
spec = importlib.util.spec_from_file_location("analyze_face_recog_log", SCRIPT_PATH)
|
|
module = importlib.util.module_from_spec(spec)
|
|
sys.modules[spec.name] = module
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
class FaceRecogLogAnalysisTest(unittest.TestCase):
|
|
def test_summarizes_face_matches_tracks_and_uploads(self):
|
|
module = load_module()
|
|
sample = textwrap.dedent(
|
|
"""
|
|
RK3588 Media Server v0.1.0 (git abc1234)
|
|
[1000][I] [ai_face_recog] gallery loaded: n=15 dim=512
|
|
[1001][I] [ai_face_recog] start id=face_recog align=true thr_accept=0.450000 thr_margin=0.050000 infer_interval_ms=500 shared_target_key=graph:cam1:tracked_targets debug=true debug_log_matches=true debug_min_log_interval_ms=0
|
|
[1002][I] [ai_face_recog] track_assoc id=face_recog frame=10 source=shared_state person_class_id=0 face_bbox=(10,20,30,40) dets=1 person_dets=1 tracked_person_dets=1 containing_tracked_person_dets=1 best_track_id=7 best_overlap=900.0
|
|
[1003][I] [ai_face_recog] frame id=face_recog frame=10 faces_in=2 recog_items=2
|
|
[1004][I] [ai_face_recog] match id=face_recog frame=10 status=known person_track_id=7 candidate=reg_001 candidate_id=1 best_sim=0.58 second_sim=0.44 sim_margin=0.14 bbox=(10,20,30,40)
|
|
[1005][I] [ai_face_recog] match id=face_recog frame=10 status=uncertain person_track_id=-1 candidate=reg_002 candidate_id=2 best_sim=0.42 second_sim=0.39 sim_margin=0.03 bbox=(50,60,12,18)
|
|
[1005][I] [alarm] unknown_candidate rule=unknown_face frame=10 item=0 status=uncertain track_id=7 candidate_id=2 candidate=reg_002 best_sim=0.420 second_sim=0.390 margin=0.030 bbox=(50.000,60.000,12.000,18.000) area_ratio=0.000104 aspect=0.667 rule_matched=false reject_reason=min_face_area_ratio reject_detail=area_ratio=0.000104 min=0.001000 track_age_ms=0 quality_hits=0/4 min_track_age_ms=2000 reported_known=false reported_unknown=false gate=rule_rejected
|
|
[1005][I] [alarm] unknown_candidate rule=unknown_face frame=10 item=1 status=uncertain track_id=8 candidate_id=3 candidate=reg_003 best_sim=0.360 second_sim=0.320 margin=0.040 bbox=(100.000,100.000,40.000,60.000) area_ratio=0.001157 aspect=0.667 rule_matched=true reject_reason=- reject_detail=- track_age_ms=500 quality_hits=1/4 min_track_age_ms=2000 reported_known=false reported_unknown=false gate=waiting_track_age
|
|
[1006][I] [ALARM][info] 2026-04-17 10:00:00 node=alarm rule=known_person:reg_001 frame=10 detections=[]
|
|
[1007][I] [ExternalApiAction] token fetched successfully
|
|
[1008][I] [ExternalApiAction] send ok http=200 alarm_content=known_person:reg_001 pic_url=a video_url=b
|
|
"""
|
|
).strip().splitlines()
|
|
|
|
summary = module.analyze_lines(sample)
|
|
|
|
self.assertEqual(summary.version_git, "abc1234")
|
|
self.assertEqual(summary.gallery_count, 15)
|
|
self.assertEqual(summary.gallery_dim, 512)
|
|
self.assertEqual(summary.shared_target_key, "graph:cam1:tracked_targets")
|
|
self.assertEqual(summary.match_total, 2)
|
|
self.assertEqual(summary.status_counts["known"], 1)
|
|
self.assertEqual(summary.status_counts["uncertain"], 1)
|
|
self.assertEqual(summary.track_id_missing, 1)
|
|
self.assertEqual(summary.alarm_counts["known_person:reg_001"], 1)
|
|
self.assertEqual(summary.external_send_counts["ok"], 1)
|
|
self.assertEqual(summary.quantiles["known"]["best_sim"]["max"], 0.58)
|
|
self.assertNotIn("unknown", summary.quantiles)
|
|
self.assertEqual(summary.unknown_candidate_total, 2)
|
|
self.assertEqual(summary.unknown_candidate_reject_counts["min_face_area_ratio"], 1)
|
|
self.assertEqual(summary.unknown_candidate_gate_counts["waiting_track_age"], 1)
|
|
self.assertEqual(summary.unknown_candidate_rule_matched, 1)
|
|
self.assertEqual(summary.unknown_candidate_track_summaries[0]["track_id"], 8)
|
|
self.assertEqual(summary.unknown_candidate_track_summaries[0]["max_quality_hits"], 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|