mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 13:33:42 +08:00
Separate stacked speed-limit panels before reading numbers
This commit is contained in:
@@ -267,6 +267,25 @@ class HistoryEntry:
|
||||
created_at: float
|
||||
strong_consensus: bool = False
|
||||
|
||||
def _primary_regulatory_panel(image):
|
||||
height, width = image.shape[:2]
|
||||
if image.dtype != np.uint8 or width < 24 or height < 1.8 * width:
|
||||
return image
|
||||
|
||||
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
||||
_, mask = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
|
||||
for foreground in (mask >= 128, mask < 128):
|
||||
occupied = foreground[:, int(width * .2):int(width * .8)].mean(1) > .8
|
||||
edges = np.diff(np.r_[False, occupied, False].astype(np.int8))
|
||||
runs = list(zip(np.flatnonzero(edges == 1), np.flatnonzero(edges == -1), strict=False))
|
||||
for (top, bottom), (next_top, next_bottom) in zip(runs, runs[1:], strict=False):
|
||||
if (top <= .3 * width and .75 * width <= bottom - top <= 1.6 * width and
|
||||
next_bottom - next_top >= .5 * width and .02 * width <= next_top - bottom <= .15 * width):
|
||||
# Keep a separate lower plate, such as MINIMUM, out of the number reader.
|
||||
return image[:min(height, int(bottom + .03 * width))]
|
||||
return image
|
||||
|
||||
|
||||
class VisionModelCore:
|
||||
"""The frozen active detector/classifier path, with no camera or Params ownership."""
|
||||
|
||||
@@ -692,6 +711,7 @@ class VisionModelCore:
|
||||
speed_class_count = len(US_CLASSIFIER_SPEED_VALUES)
|
||||
|
||||
input_size = self.classifier_input_size
|
||||
sign_crop = _primary_regulatory_panel(sign_crop)
|
||||
padded_crop = self._square_resize(sign_crop, size=input_size)
|
||||
blob = cv2.dnn.blobFromImage(padded_crop, scalefactor=1 / 255.0, size=(input_size, input_size), swapRB=True, crop=False)
|
||||
self.classifier_net.setInput(blob)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
|
||||
from openpilot.starpilot.speed_limits.vision.model import (
|
||||
US_CLASSIFIER_SPEED_VALUES, VisionModelCore, _primary_regulatory_panel,
|
||||
)
|
||||
|
||||
|
||||
def stacked_panels():
|
||||
image = np.full((200, 100, 3), 200, dtype=np.uint8)
|
||||
image[5:105, 10:90] = 20
|
||||
image[108:190, 10:90] = 20
|
||||
return image
|
||||
|
||||
|
||||
class TestSpeedPanels(unittest.TestCase):
|
||||
def test_separate_lower_plate_is_excluded(self):
|
||||
image = stacked_panels()
|
||||
crop = _primary_regulatory_panel(image)
|
||||
self.assertGreaterEqual(crop.shape[0], 105)
|
||||
self.assertLessEqual(crop.shape[0], 108)
|
||||
np.testing.assert_array_equal(crop, image[:crop.shape[0]])
|
||||
|
||||
def test_single_plate_and_short_header_keep_original_input(self):
|
||||
single = np.full((200, 100, 3), 200, dtype=np.uint8)
|
||||
single[5:195, 10:90] = 20
|
||||
header = single.copy()
|
||||
header[30:40] = 200
|
||||
for image in (single, header, stacked_panels().astype(np.float32), np.zeros((40, 30, 3), dtype=np.uint8)):
|
||||
self.assertIs(_primary_regulatory_panel(image), image)
|
||||
|
||||
def test_read_uses_one_existing_classifier_forward(self):
|
||||
class Net:
|
||||
calls = 0
|
||||
|
||||
def setInput(self, blob):
|
||||
self.blob = blob
|
||||
|
||||
def forward(self):
|
||||
self.calls += 1
|
||||
scores = np.zeros((1, len(US_CLASSIFIER_SPEED_VALUES) + 1), dtype=np.float32)
|
||||
scores[0, US_CLASSIFIER_SPEED_VALUES.index(70)] = .99
|
||||
return scores
|
||||
|
||||
core = object.__new__(VisionModelCore)
|
||||
core.classifier_net = Net()
|
||||
core.classifier_input_size = 128
|
||||
core.classifier_logits_layer = None
|
||||
core.last_classifier_forward_count = 0
|
||||
core.last_classifier_forward_duration_s = 0.
|
||||
result = core._classify_speed_limit_from_model(stacked_panels())
|
||||
assert result is not None
|
||||
self.assertEqual(result[0], 70)
|
||||
self.assertEqual(core.classifier_net.calls, 1)
|
||||
self.assertEqual(core.last_classifier_forward_count, 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"protected_inventory_sha256": "46a4163eb60a227519f3e01c28cfad309e5eefd27132298487d072c43be4a31c", "schema_version": 1}
|
||||
{"protected_inventory_sha256": "3f48edce7f387d0e45d93fd3e6dd8cdad10f0e88def45bb818e65882bf2d977e", "schema_version": 1}
|
||||
|
||||
Reference in New Issue
Block a user