"""视差取点器测试(规格 §6.1/§11.4:同侧边缘、框宽差隔离、越窗回退、边界含等号)。""" import pytest from stereo_ranger import Detection, DisparitySource, StereoConfig, sample_point, select_disparity CFG = StereoConfig() def _box(x1: float, x2: float, *, y1: float = 500.0, y2: float = 540.0) -> Detection: return Detection(x1, y1, x2, y2) def _disparity(left: Detection, right: Detection): return select_disparity(sample_point(left), sample_point(right), CFG) def test_left_edge_used_as_primary_sampling(): d = _disparity(_box(1000.0, 1060.0), _box(990.4, 1050.4)) assert d.source is DisparitySource.LEFT_EDGE assert d.d_px == pytest.approx(9.6) assert d.in_domain and d.positive and not d.fallback_used def test_box_width_difference_does_not_enter_edge_disparity(): # §11.4:构造两目不等宽框,断言同侧边缘视差相同(框宽差不进入视差) left = _box(1000.0, 1100.0) # 宽 100 right_narrow = _box(994.0, 1024.0) # 宽 30,左边缘差同 6 px right_wide = _box(994.0, 1094.0) # 宽 100 d_narrow = _disparity(left, right_narrow) d_wide = _disparity(left, right_wide) assert d_narrow.d_px == pytest.approx(6.0) assert d_wide.d_px == pytest.approx(6.0) def test_center_disparity_would_be_polluted_by_width_difference(): # 对照:中心视差 41 px = 边缘视差 6 px + 框宽差的一半 35 px,证明主取点选择边缘的理由 left = _box(1000.0, 1100.0) # 宽 100, center 1050 right_narrow = _box(994.0, 1024.0) # 宽 30, center 1009 assert (left.cx - right_narrow.cx) == pytest.approx(41.0) def test_center_fallback_when_edge_out_of_window(): # 边缘视差 60 px 越窗(> 57.6),中心视差 40 px 在域内 → 回退中心并标记 left = _box(1000.0, 1060.0) # center 1030 right = _box(940.0, 1040.0) # center 990 d = _disparity(left, right) assert d.fallback_used is True assert d.source is DisparitySource.CENTER_FALLBACK assert d.d_px == pytest.approx(40.0) assert d.in_domain and d.positive def test_both_out_of_window_keeps_edge_value_for_diagnostics(): left = _box(1000.0, 1200.0) # center 1100 right = _box(900.0, 1000.0) # center 950 d = _disparity(left, right) assert d.d_px == pytest.approx(100.0) # 边缘值保留(诊断 + 违例告警) assert not d.in_domain and not d.fallback_used and d.positive def test_domain_boundaries_are_inclusive(): assert _disparity(_box(1000.0, 1060.0), _box(997.0, 1057.0)).in_domain # D = 3.0 = 下限 # 上限用二进制可精确表示的 57.5 构造:十进制字面量 57.6 无法精确表示, # 框坐标相减会落到 57.6 常量之上,边界断言被浮点舍入干扰 exact_cfg = StereoConfig(disparity_max_px=57.5) left, right = _box(1000.0, 1060.0), _box(942.5, 1002.5) assert select_disparity(sample_point(left), sample_point(right), exact_cfg).in_domain # D = 57.5 = 上限 def test_negative_disparity_flagged_as_violation(): d = _disparity(_box(1000.0, 1060.0), _box(1010.0, 1070.0)) assert d.d_px == pytest.approx(-10.0) assert not d.positive and not d.in_domain def test_non_finite_box_marked_unusable(): assert sample_point(Detection(float("nan"), 0.0, 10.0, 10.0)).finite is False assert sample_point(Detection(0.0, 0.0, 10.0, 10.0)).finite is True