mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-11-05 13:20:31 +03:00
Drop interpolated_percentile, keep only average_boxes
Per review: reimplementing np.percentile hurts readability and risks divergence from numpy (e.g. numpy 2.x). Revert update_position to np.percentile and remove the helper; keep only the average_boxes change (sum()/len() instead of np.mean), which stays bit-identical. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
d80d020c86
commit
4f18a9fdac
@@ -4,7 +4,7 @@ import unittest
|
||||
import numpy as np
|
||||
|
||||
from frigate.track.tracked_object import TrackedObjectAttribute
|
||||
from frigate.util.object import average_boxes, interpolated_percentile
|
||||
from frigate.util.object import average_boxes
|
||||
|
||||
|
||||
class TestBoxStatistics(unittest.TestCase):
|
||||
@@ -18,19 +18,6 @@ class TestBoxStatistics(unittest.TestCase):
|
||||
expected = [float(np.mean([b[i] for b in boxes])) for i in range(4)]
|
||||
self.assertEqual(average_boxes(boxes), expected)
|
||||
|
||||
def test_interpolated_percentile_matches_numpy(self) -> None:
|
||||
rng = random.Random(1)
|
||||
for _ in range(5000):
|
||||
values = [rng.randint(0, 5000) for _ in range(rng.randint(1, 10))]
|
||||
for q in (15, 85, 50):
|
||||
self.assertEqual(
|
||||
interpolated_percentile(values, q),
|
||||
float(np.percentile(values, q)),
|
||||
)
|
||||
|
||||
def test_interpolated_percentile_single_value(self) -> None:
|
||||
self.assertEqual(interpolated_percentile([42], 15), 42.0)
|
||||
|
||||
|
||||
class TestAttribute(unittest.TestCase):
|
||||
def test_overlapping_object_selection(self) -> None:
|
||||
|
||||
@@ -27,11 +27,7 @@ from frigate.util.image import (
|
||||
get_histogram,
|
||||
intersection_over_union,
|
||||
)
|
||||
from frigate.util.object import (
|
||||
average_boxes,
|
||||
interpolated_percentile,
|
||||
median_of_boxes,
|
||||
)
|
||||
from frigate.util.object import average_boxes, median_of_boxes
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -432,10 +428,10 @@ class NorfairTracker(ObjectTracker):
|
||||
position["xmaxs"].append(xmax)
|
||||
position["ymaxs"].append(ymax)
|
||||
# by using percentiles here, we hopefully remove outliers
|
||||
position["xmin"] = interpolated_percentile(position["xmins"], 15)
|
||||
position["ymin"] = interpolated_percentile(position["ymins"], 15)
|
||||
position["xmax"] = interpolated_percentile(position["xmaxs"], 85)
|
||||
position["ymax"] = interpolated_percentile(position["ymaxs"], 85)
|
||||
position["xmin"] = np.percentile(position["xmins"], 15)
|
||||
position["ymin"] = np.percentile(position["ymins"], 15)
|
||||
position["xmax"] = np.percentile(position["xmaxs"], 85)
|
||||
position["ymax"] = np.percentile(position["ymaxs"], 85)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -354,25 +354,6 @@ def median_of_boxes(boxes: list[list[int, int, int, int]]) -> list[int, int, int
|
||||
return sorted_boxes[int(len(sorted_boxes) / 2.0)]
|
||||
|
||||
|
||||
def interpolated_percentile(values: list[int], q: float) -> float:
|
||||
"""Linear-interpolated percentile, matching numpy.percentile for the small
|
||||
lists used in position smoothing without the per-call numpy overhead."""
|
||||
ordered = sorted(values)
|
||||
n = len(ordered)
|
||||
if n == 1:
|
||||
return float(ordered[0])
|
||||
rank = (q / 100.0) * (n - 1)
|
||||
lo = int(rank)
|
||||
frac = rank - lo
|
||||
if frac == 0.0:
|
||||
return float(ordered[lo])
|
||||
diff = ordered[lo + 1] - ordered[lo]
|
||||
# numpy's lerp switches sides at frac >= 0.5 to limit rounding error
|
||||
if frac < 0.5:
|
||||
return ordered[lo] + diff * frac
|
||||
return ordered[lo + 1] - diff * (1.0 - frac)
|
||||
|
||||
|
||||
def intersects_any(box_a, boxes):
|
||||
for box in boxes:
|
||||
if box_overlaps(box_a, box):
|
||||
|
||||
Reference in New Issue
Block a user