from hermes_vision.detect import Face from hermes_vision.tracking import FaceTracker def f(x, y=100, w=80, h=80): return Face(x, y, w, h, 0.9) def test_a_face_keeps_its_track_id_and_age_grows(): tr = FaceTracker() ids = [] for i in range(8): (t,) = tr.update([f(100 + 3 * i)], i * 0.25) ids.append(t.id) assert ids == [1] * 8 and abs(t.age(1.75) - 1.75) < 1e-9 def test_two_people_get_two_ids_and_keep_them_when_they_swap_order(): tr = FaceTracker() a, b = tr.update([f(100), f(500)], 0.0) b2, a2 = tr.update([f(502), f(102)], 0.25) # reported in the other order assert (a.id, b.id) == (a2.id, b2.id) and a.id != b.id def test_a_track_survives_a_short_gap_but_not_a_long_one(): tr = FaceTracker(max_age_s=1.5) (t,) = tr.update([f(100)], 0.0) tr.update([], 1.0) # nobody for a second (t2,) = tr.update([f(100)], 1.2) assert t2.id == t.id tr.update([], 1.3) tr.update([], 3.5) # gone for over max_age (t3,) = tr.update([f(100)], 3.6) assert t3.id != t.id def test_identity_is_resolved_for_new_tracks_and_rechecked_once_a_second(): calls = [] tr = FaceTracker(recheck_s=1.0) ident = lambda face: (calls.append(face), ('Kyle', 0.8))[1] for i in range(8): # 4 Hz for two seconds (t,) = tr.update([f(100 + i)], i * 0.25, ident) assert t.name == 'Kyle' and t.similarity == 0.8 assert len(calls) == 2 # at t=0 and again at t=1.0 def test_a_stranger_is_unknown_not_named(): tr = FaceTracker() (t,) = tr.update([f(100)], 0.0, lambda face: ('', 0.12)) assert t.name == '' and t.similarity == 0.12 def test_without_an_identifier_nothing_is_named(): (t,) = FaceTracker().update([f(100)], 0.0) assert t.name == '' and t.id == 1 def test_iou(): from hermes_vision.recognize import iou a = Face(0, 0, 100, 100) assert iou(a, a) == 1.0 assert iou(a, Face(200, 200, 50, 50)) == 0.0 assert 0.3 < iou(a, Face(50, 0, 100, 100)) < 0.4