diff --git a/opengait/demo/pipeline.py b/opengait/demo/pipeline.py index 5c9e46a..ed3e645 100644 --- a/opengait/demo/pipeline.py +++ b/opengait/demo/pipeline.py @@ -438,18 +438,22 @@ class ScoliosisPipeline: copy_method = cast( Callable[[], object] | None, getattr(v, "copy", None) ) - if copy_method is not None: + if copy_method is not None and callable(copy_method): cached[k] = copy_method() else: cached[k] = v self._last_viz_payload = cached - # Use cached payload if current is None - viz_data = ( - viz_payload - if viz_payload is not None - else self._last_viz_payload - ) + if viz_payload is not None: + viz_data = viz_payload + elif self._last_viz_payload is not None: + viz_data = dict(self._last_viz_payload) + viz_data["bbox"] = None + viz_data["bbox_mask"] = None + viz_data["label"] = None + viz_data["confidence"] = None + else: + viz_data = None if viz_data is not None: # Cast viz_payload to dict for type checking diff --git a/tests/demo/test_pipeline.py b/tests/demo/test_pipeline.py index a6057be..bb07366 100644 --- a/tests/demo/test_pipeline.py +++ b/tests/demo/test_pipeline.py @@ -790,12 +790,7 @@ def test_pipeline_visualizer_updates_on_no_detection() -> None: assert call["confidence"] is None # No confidence when no detection -def test_pipeline_visualizer_uses_cached_detection_on_no_detection() -> None: - """Test that visualizer reuses last valid detection when current frame has no detection. - - This is a regression test for the cache-reuse behavior when person temporarily - disappears from frame. The last valid silhouette/mask should be displayed. - """ +def test_pipeline_visualizer_clears_bbox_on_no_detection() -> None: from opengait.demo.pipeline import ScoliosisPipeline # Create a minimal pipeline with mocked dependencies @@ -884,7 +879,6 @@ def test_pipeline_visualizer_uses_cached_detection_on_no_detection() -> None: assert mask_raw_calls[0] is not None, "Frame 0 should have valid mask" assert mask_raw_calls[1] is not None, "Frame 1 should have valid mask" - # Frames 2 and 3 should reuse the cached mask from frame 1 (not None) assert mask_raw_calls[2] is not None, ( "Frame 2 (no detection) should display cached mask from last valid detection, " "not None/blank" @@ -902,10 +896,21 @@ def test_pipeline_visualizer_uses_cached_detection_on_no_detection() -> None: assert segmentation_inputs[1] is not None assert segmentation_inputs[2] is not None assert segmentation_inputs[3] is not None + bbox_calls = [call["bbox"] for call in mock_viz.update_calls] + assert bbox_calls[0] == dummy_bbox_frame + assert bbox_calls[1] == dummy_bbox_frame + assert bbox_calls[2] is None + assert bbox_calls[3] is None assert bbox_mask_calls[0] == dummy_bbox_mask assert bbox_mask_calls[1] == dummy_bbox_mask - assert bbox_mask_calls[2] == dummy_bbox_mask - assert bbox_mask_calls[3] == dummy_bbox_mask + assert bbox_mask_calls[2] is None + assert bbox_mask_calls[3] is None + label_calls = [call["label"] for call in mock_viz.update_calls] + confidence_calls = [call["confidence"] for call in mock_viz.update_calls] + assert label_calls[2] is None + assert label_calls[3] is None + assert confidence_calls[2] is None + assert confidence_calls[3] is None if mask_raw_calls[1] is not None and mask_raw_calls[2] is not None: assert mask_raw_calls[1] is not mask_raw_calls[2], (