From 10b43948797335adbc322ae2e2d1651795cb5877 Mon Sep 17 00:00:00 2001 From: patrykorwat Date: Tue, 18 Aug 2026 06:48:23 +0000 Subject: [PATCH] fix(axelera): emit normalized box coordinates (0..1) Frigate detect() interprets detector boxes as fractions of the region and discards any box resolving outside the frame. The plugin returned pixel coordinates, so every detection was silently filtered out and no events were ever created despite a working inference chain. Normalize by model width/height (same contract as memryx/onnx). Live: 0 events -> 27 events in ~70 s after the fix. --- frigate/detectors/plugins/axelera.py | 16 ++++++++++++++-- frigate/test/test_axelera_detector.py | 6 +++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/frigate/detectors/plugins/axelera.py b/frigate/detectors/plugins/axelera.py index 5bf0e77aef..e1ce7407cd 100644 --- a/frigate/detectors/plugins/axelera.py +++ b/frigate/detectors/plugins/axelera.py @@ -177,7 +177,12 @@ class _AxeleraInference: yield frame def _detection_rows(self, frame_result) -> list: - """Convert a stream result into (class_id, score, ymin, xmin, ymax, xmax) rows.""" + """Convert a stream result into (class_id, score, ymin, xmin, ymax, xmax) rows. + + Box coordinates are NORMALIZED [0..1]: Frigate's detect() multiplies + them by the region size, pixel boxes are discarded as outside the frame + (zero events despite working detections). + """ dets = getattr(frame_result, "detections", None) or [] rows = [] for det in dets: @@ -202,7 +207,14 @@ class _AxeleraInference: continue x0, y0, x1, y1 = box rows.append( - (class_id, score, y0, x0, min(y1, self._height), min(x1, self._width)) + ( + class_id, + score, + y0 / self._height, + x0 / self._width, + min(y1, self._height) / self._height, + min(x1, self._width) / self._width, + ) ) rows.sort(key=lambda r: r[1], reverse=True) return rows[:MAX_ROWS] diff --git a/frigate/test/test_axelera_detector.py b/frigate/test/test_axelera_detector.py index 34e82bcb96..f0f9cfd489 100644 --- a/frigate/test/test_axelera_detector.py +++ b/frigate/test/test_axelera_detector.py @@ -227,8 +227,8 @@ class TestAxeleraInference(unittest.TestCase): ids = sorted(int(r[0]) for r in out if r[1] > 0) self.assertEqual(ids, [0, 7]) # unknown_label dropped rows = {int(r[0]): r for r in out if r[1] > 0} - # rows are [class_id, score, ymin, xmin, ymax, xmax] in pixels - self.assertEqual(tuple(rows[7][2:6]), (20.0, 10.0, 40.0, 30.0)) + # rows are [class_id, score, ymin, xmin, ymax, xmax] NORMALIZED (0..1) + self.assertEqual(tuple(rows[7][2:6]), (0.0625, 0.03125, 0.125, 0.09375)) self.assertEqual(rows[0][1], 0.55) finally: engine.stop() @@ -291,7 +291,7 @@ class TestAxeleraInference(unittest.TestCase): truck = [r for r in out if int(r[0]) == 7 and r[1] > 0] self.assertTrue(truck, "expected truck row") self.assertAlmostEqual(float(truck[0][1]), 0.8, places=2) - self.assertEqual(tuple(truck[0][2:6]), (20.0, 10.0, 40.0, 30.0)) + self.assertEqual(tuple(truck[0][2:6]), (0.0625, 0.03125, 0.125, 0.09375)) finally: engine.stop()