Avoid unused speed-sign material masks

This commit is contained in:
firestar5683
2026-11-11 17:04:09 +00:00
committed by Dominick Thompson
parent 18f296956d
commit b70f2f5980
3 changed files with 93 additions and 15 deletions
@@ -474,45 +474,53 @@ class VisionModelCore:
white_mask = ((value >= REGULATORY_WHITE_VALUE_MIN) & (saturation <= REGULATORY_WHITE_SAT_MAX)).astype(np.uint8)
dark_mask = ((value <= REGULATORY_DARK_VALUE_MAX) & (saturation <= REGULATORY_DARK_SAT_MAX)).astype(np.uint8)
white_ratio = float(white_mask.mean())
dark_ratio = float(dark_mask.mean())
if white_ratio < REGULATORY_MIN_WHITE_RATIO or dark_ratio < REGULATORY_MIN_DARK_RATIO:
return False
yellow_mask = (
(hue >= REGULATORY_YELLOW_HUE_MIN) &
(hue <= REGULATORY_YELLOW_HUE_MAX) &
(saturation >= REGULATORY_YELLOW_SAT_MIN) &
(value >= REGULATORY_YELLOW_VALUE_MIN)
).astype(np.uint8)
yellow_ratio = float(yellow_mask.mean())
if yellow_ratio > REGULATORY_MAX_YELLOW_RATIO and yellow_ratio > white_ratio * 0.45:
return False
red_mask = (
(((hue <= REGULATORY_RED_LOW_HUE_MAX) | (hue >= REGULATORY_RED_HIGH_HUE_MIN))) &
(saturation >= REGULATORY_RED_SAT_MIN) &
(value >= REGULATORY_RED_VALUE_MIN)
).astype(np.uint8)
red_ratio = float(red_mask.mean())
if red_ratio > REGULATORY_MAX_RED_RATIO and red_ratio > white_ratio * 0.35:
return False
green_mask = (
(hue >= REGULATORY_GREEN_HUE_MIN) &
(hue <= REGULATORY_GREEN_HUE_MAX) &
(saturation >= REGULATORY_COLORED_SAT_MIN) &
(value >= REGULATORY_COLORED_VALUE_MIN)
).astype(np.uint8)
green_ratio = float(green_mask.mean())
if green_ratio > REGULATORY_MAX_GREEN_RATIO and green_ratio > white_ratio * 0.60:
return False
blue_mask = (
(hue >= REGULATORY_BLUE_HUE_MIN) &
(hue <= REGULATORY_BLUE_HUE_MAX) &
(saturation >= REGULATORY_COLORED_SAT_MIN) &
(value >= REGULATORY_COLORED_VALUE_MIN)
).astype(np.uint8)
white_ratio = float(white_mask.mean())
dark_ratio = float(dark_mask.mean())
yellow_ratio = float(yellow_mask.mean())
red_ratio = float(red_mask.mean())
green_ratio = float(green_mask.mean())
blue_ratio = float(blue_mask.mean())
if white_ratio < REGULATORY_MIN_WHITE_RATIO or dark_ratio < REGULATORY_MIN_DARK_RATIO:
return False
if yellow_ratio > REGULATORY_MAX_YELLOW_RATIO and yellow_ratio > white_ratio * 0.45:
return False
if red_ratio > REGULATORY_MAX_RED_RATIO and red_ratio > white_ratio * 0.35:
return False
if green_ratio > REGULATORY_MAX_GREEN_RATIO and green_ratio > white_ratio * 0.60:
return False
if blue_ratio > REGULATORY_MAX_BLUE_RATIO and blue_ratio > white_ratio * 0.60:
return False
@@ -0,0 +1,70 @@
"""Pure regulatory-material pixels; no model construction or inference."""
import unittest
from unittest.mock import patch
import numpy as np
from openpilot.starpilot.speed_limits.vision import model
@unittest.skipIf(model.cv2 is None, 'OpenCV is optional')
class TestMaterialValidation(unittest.TestCase):
def validate(self, image):
return model.VisionModelCore._is_regulatory_speed_sign(None, image)
def panel(self, hue=None):
hsv = np.zeros((100, 80, 3), np.uint8)
if hue is not None:
hsv[:] = (hue, 255, 255)
hsv[10:90, 15:65] = (0, 0, 255)
hsv[40:50, 25:55] = 0
return model.cv2.cvtColor(hsv, model.cv2.COLOR_HSV2BGR)
def test_plain_panel_and_each_color_veto(self):
self.assertTrue(self.validate(self.panel()))
for hue in (25, 0, 60, 110):
with self.subTest(hue=hue):
self.assertFalse(self.validate(self.panel(hue)))
def test_empty_white_dark_and_component_rejections(self):
self.assertFalse(self.validate(np.empty((0, 0, 3), np.uint8)))
for value in (0, 255):
self.assertFalse(self.validate(np.full((100, 80, 3), value, np.uint8)))
image = np.zeros((100, 80, 3), np.uint8)
image[40:60, 5:75] = 255
self.assertFalse(self.validate(image))
def test_early_rejection_does_not_evaluate_later_hue_masks(self):
operations = []
class Hue:
def __init__(self, values):
self.values = values
def __ge__(self, value):
operations.append(('ge', value))
return self.values >= value
def __le__(self, value):
operations.append(('le', value))
return self.values <= value
class HSV:
def __init__(self, values):
self.values = values
def __getitem__(self, key):
values = self.values[key]
return Hue(values) if key[2] == 0 else values
for image, expected in ((np.zeros((100, 80, 3), np.uint8), []),
(self.panel(25), [('ge', 12), ('le', 45)])):
operations.clear()
hsv = model.cv2.cvtColor(image, model.cv2.COLOR_BGR2HSV)
with patch.object(model.cv2, 'cvtColor', return_value=HSV(hsv)):
self.assertFalse(self.validate(image))
self.assertEqual(operations, expected)
if __name__ == '__main__':
unittest.main()
+1 -1
View File
@@ -1 +1 @@
{"protected_inventory_sha256": "146409f6a49f160356ba631732972e7870ff88605cee0497e77787de656fb9bd", "schema_version": 1}
{"protected_inventory_sha256": "e2a34c53b21d7fe71b765a7f4889f8139ee4aa3a0c4d25c3bd41cf195ed94aa0", "schema_version": 1}