feat: add RMSE-based fallback for depth pooling

This commit is contained in:
2026-02-07 09:07:23 +00:00
parent 8f6aee7f22
commit 8dbf892ce8
2 changed files with 153 additions and 11 deletions
@@ -140,13 +140,15 @@ def test_pool_size_5_integration(mock_dependencies):
assert any_pooled
# Check that the depth map passed to verify is the median (2.0)
# Note: verify is called twice now (once for check, once for final)
# We check the last call
args, _ = mock_verify.call_args
passed_depth_map = args[2]
expected_median = np.ones((10, 10)) * 2.0
np.testing.assert_allclose(passed_depth_map, expected_median)
# Verify metadata was added
# Verify metadata
assert "depth_pool" in results[serial]
assert results[serial]["depth_pool"]["pooled"] is True # pyright: ignore
assert results[serial]["depth_pool"]["pool_size_actual"] == 3 # pyright: ignore
@@ -251,3 +253,91 @@ def test_pool_fallback_insufficient_valid(mock_dependencies):
results[serial]["depth_pool"]["fallback_reason"] # pyright: ignore
== "insufficient_valid_points"
)
def test_pool_fallback_worse_rmse(mock_dependencies):
"""
Test fallback to single frame when pooled result has worse RMSE.
"""
mock_verify, _, mock_echo = mock_dependencies
serial = "123456"
results = {serial: {"pose": "1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1"}}
# Create frames
f1 = MagicMock()
f1.depth_map = np.ones((10, 10)) * 2.0
f1.confidence_map = np.zeros((10, 10))
f2 = MagicMock()
f2.depth_map = np.ones((10, 10)) * 2.2
f2.confidence_map = np.zeros((10, 10))
vfs = [
{
"frame": f1,
"ids": np.array([[1]]),
"corners": np.zeros((1, 4, 2)),
"score": 100,
},
{
"frame": f2,
"ids": np.array([[1]]),
"corners": np.zeros((1, 4, 2)),
"score": 90,
},
]
verification_frames = {serial: vfs}
marker_geometry = {1: np.zeros((4, 3))}
camera_matrices = {serial: np.eye(3)}
# Mock verify_extrinsics_with_depth to return worse RMSE for pooled
# First call is pooled, second is best single frame
res_pooled = MagicMock()
res_pooled.rmse = 0.10
res_pooled.n_valid = 100
res_pooled.n_total = 100
res_best = MagicMock()
res_best.rmse = 0.05
res_best.n_valid = 100
res_best.n_total = 100
# Third call is the final verification with the chosen depth (best frame)
res_final = MagicMock()
res_final.rmse = 0.05
res_final.n_valid = 100
res_final.n_total = 100
res_final.residuals = []
mock_verify.side_effect = [res_pooled, res_best, res_final]
# Run with pool_size=2
apply_depth_verify_refine_postprocess(
results=results, # type: ignore
verification_frames=verification_frames, # pyright: ignore
marker_geometry=marker_geometry,
camera_matrices=camera_matrices, # pyright: ignore
verify_depth=True,
refine_depth=False,
use_confidence_weights=False,
depth_confidence_threshold=50,
depth_pool_size=2,
)
# Check for fallback message
any_fallback = any(
"worse than single frame" in str(call.args[0])
for call in mock_echo.call_args_list
)
assert any_fallback
# Verify metadata
assert results[serial]["depth_pool"]["pooled"] is False # pyright: ignore
assert (
results[serial]["depth_pool"]["fallback_reason"] # pyright: ignore
== "worse_verify_rmse"
)
assert results[serial]["depth_pool"]["pooled_rmse"] == 0.10 # pyright: ignore
assert results[serial]["depth_pool"]["single_rmse"] == 0.05 # pyright: ignore