From 3d23f9028de480a328590942e4681eb640e2f9e7 Mon Sep 17 00:00:00 2001 From: AmitMY Date: Sat, 20 Jun 2026 10:10:00 +0200 Subject: [PATCH] Fix flaky optical flow test: compare numbers, not rendered image The test rendered the optical flow as a matplotlib heatmap and compared the PNG against a checked-in reference with a 0.001 RMS tolerance. That comparison depends on matplotlib/freetype rendering, which drifts across CI runners and matplotlib versions (unpinned deps pull the newest on 3.11/3.12), so the test flaked on master while the underlying computation never changed. OpticalFlowCalculator is pure, deterministic numpy. Compare its output to a numeric .npy reference via np.allclose instead, removing matplotlib from the test entirely. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/python/tests/data/optical_flow.npy | Bin 0 -> 67728 bytes src/python/tests/data/optical_flow.png | Bin 14087 -> 0 bytes src/python/tests/optical_flow_test.py | 32 +++++++++---------------- 3 files changed, 11 insertions(+), 21 deletions(-) create mode 100644 src/python/tests/data/optical_flow.npy delete mode 100644 src/python/tests/data/optical_flow.png diff --git a/src/python/tests/data/optical_flow.npy b/src/python/tests/data/optical_flow.npy new file mode 100644 index 0000000000000000000000000000000000000000..c25b9512b8ae7eb9fd2a7d21d9c9924f1d5a3871 GIT binary patch literal 67728 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 diff --git a/src/python/tests/optical_flow_test.py b/src/python/tests/optical_flow_test.py index d06f636..62769f3 100644 --- a/src/python/tests/optical_flow_test.py +++ b/src/python/tests/optical_flow_test.py @@ -1,10 +1,9 @@ """ Module for testing optical flow computations. Provides test cases for optical flow computation from pose landmarks data. """ -import tempfile from unittest import TestCase -from matplotlib.testing.compare import compare_images +import numpy as np from pose_format.numpy.representation.distance import DistanceRepresentation from pose_format.pose import Pose @@ -18,13 +17,11 @@ class TestOpticalFlow(TestCase): def test_optical_flow(self): """ - Tests optical flow from pose landmarks data and - visualize the computed flow using a heatmap. - - Compares the generated heatmap with the reference image provided in `data/optical_flow.png` to validate the correctness of the omputed optical flow. - - Raises: - AssertionError: If the computed optical flow visualization does not match the reference image. + Tests optical flow from pose landmarks data against a numeric reference. + + Compares the computed flow with `data/optical_flow.npy`. The reference is + the raw numeric output (not a rendered image), so the test is independent + of matplotlib/freetype rendering differences across environments. """ calculator = OpticalFlowCalculator(fps=30, distance=DistanceRepresentation()) @@ -32,16 +29,9 @@ def test_optical_flow(self): pose = Pose.read(f.read()) pose = pose.get_components(["POSE_LANDMARKS", "RIGHT_HAND_LANDMARKS", "LEFT_HAND_LANDMARKS"]) - flow = calculator(pose.body.data) - flow = flow.squeeze(axis=1) - print(flow.shape) - - # Matplotlib heatmap - import matplotlib.pyplot as plt - plt.imshow(flow.T) - plt.tight_layout() - - fp = tempfile.NamedTemporaryFile() - plt.savefig(fp.name, format='png') + flow = calculator(pose.body.data).squeeze(axis=1) - self.assertTrue(compare_images('tests/data/optical_flow.png', fp.name, 0.001) is None) + expected = np.load('tests/data/optical_flow.npy') + self.assertEqual(flow.shape, expected.shape) + self.assertTrue(np.allclose(flow, expected), + "Computed optical flow does not match the reference.")