74 lines
2.6 KiB
Python
74 lines
2.6 KiB
Python
"""目标隔离测试(规格 §4:track_id 优先 + 框位置最近邻、帧末老化清理)。"""
|
||
|
||
from stereo_ranger import StereoConfig, TargetStore
|
||
|
||
CFG = StereoConfig() # isolation_gate_px = 50,filter_reset_frames = 5
|
||
|
||
|
||
def test_track_key_stable_across_position_move():
|
||
store = TargetStore(CFG)
|
||
key_1 = store.resolve(0, 7, (100.0, 100.0), 1)
|
||
key_2 = store.resolve(0, 7, (400.0, 100.0), 2) # 位置大幅移动仍是同一目标
|
||
assert key_1 == key_2
|
||
assert store.count == 1
|
||
|
||
|
||
def test_nearest_neighbor_keeps_identity_within_gate():
|
||
store = TargetStore(CFG)
|
||
key_1 = store.resolve(0, None, (100.0, 100.0), 1)
|
||
key_2 = store.resolve(0, None, (130.0, 140.0), 2) # 距离 50 ≤ 门限
|
||
assert key_1 == key_2
|
||
|
||
|
||
def test_beyond_gate_creates_new_key():
|
||
store = TargetStore(CFG)
|
||
key_1 = store.resolve(0, None, (100.0, 100.0), 1)
|
||
key_2 = store.resolve(0, None, (200.0, 100.0), 2) # 距离 100 > 门限
|
||
assert key_1 != key_2
|
||
assert store.count == 2
|
||
|
||
|
||
def test_class_id_separates_states():
|
||
store = TargetStore(CFG)
|
||
assert store.resolve(0, None, (100.0, 100.0), 1) != store.resolve(1, None, (100.0, 100.0), 1)
|
||
|
||
|
||
def test_two_boxes_same_frame_claim_distinct_states():
|
||
store = TargetStore(CFG)
|
||
key_1 = store.resolve(0, None, (100.0, 100.0), 1)
|
||
key_2 = store.resolve(0, None, (110.0, 100.0), 1) # 同帧第二框不得接管已占用状态
|
||
assert key_1 != key_2
|
||
assert store.count == 2
|
||
|
||
|
||
def test_state_evicted_after_reset_frames_unseen():
|
||
store = TargetStore(CFG)
|
||
key = store.resolve(0, None, (100.0, 100.0), 1)
|
||
store.distance_filter.advance(key, 5.0)
|
||
store.consistency.advance(key, 9.6)
|
||
for frame in range(2, 7): # 第 2~6 帧:连续 5 帧缺席
|
||
store.end_frame(frame)
|
||
assert store.count == 0
|
||
assert store.distance_filter.value(key) is None
|
||
assert store.consistency.streak(key) == 0
|
||
|
||
|
||
def test_present_but_invalid_keeps_position_state():
|
||
store = TargetStore(CFG)
|
||
key = store.resolve(0, None, (100.0, 100.0), 1)
|
||
store.distance_filter.advance(key, 5.0)
|
||
for frame in range(2, 8):
|
||
store.resolve(0, None, (100.0, 100.0), frame) # 每帧仍出现
|
||
store.distance_filter.invalidate(key)
|
||
assert store.count == 1 # 位置状态保留
|
||
assert store.distance_filter.value(key) is None # 滤波状态已按门限清空
|
||
|
||
|
||
def test_clear_resets_everything():
|
||
store = TargetStore(CFG)
|
||
key = store.resolve(0, 5, (100.0, 100.0), 1)
|
||
store.distance_filter.advance(key, 5.0)
|
||
store.clear()
|
||
assert store.count == 0
|
||
assert store.distance_filter.value(key) is None
|