diff --git a/openpilot/starpilot/speed_limits/vision/model.py b/openpilot/starpilot/speed_limits/vision/model.py index 61073bcf4c..3d34223cc0 100644 --- a/openpilot/starpilot/speed_limits/vision/model.py +++ b/openpilot/starpilot/speed_limits/vision/model.py @@ -946,6 +946,12 @@ class VisionModelCore: if face_filter is not None and face_filter.reject_once((proposal_confidence, class_id, (x1, y1, x2, y2))): self.latest_detector_proposal = None return None + if (type(proposals) is list and proposal_index == len(proposals) - 1 and + expansions is DETECTOR_CLASSIFIER_EXPANSIONS and + (expand_left, expand_top, expand_right, expand_bottom, expansion_weight) == expansions[-1] and + class_id == 0 and best_score == .95 and + getattr(self, 'classifier_net', None) is not None): + continue if (type(proposals) is list and proposal_index == len(proposals) - 1 and expansions is DETECTOR_CLASSIFIER_EXPANSIONS and (expand_left, expand_top, expand_right, expand_bottom, expansion_weight) == expansions[-1] and diff --git a/openpilot/starpilot/speed_limits/vision/tests/test_vision_final_unusable_crop.py b/openpilot/starpilot/speed_limits/vision/tests/test_vision_final_unusable_crop.py index ceecaec955..3ea83762df 100644 --- a/openpilot/starpilot/speed_limits/vision/tests/test_vision_final_unusable_crop.py +++ b/openpilot/starpilot/speed_limits/vision/tests/test_vision_final_unusable_crop.py @@ -119,5 +119,70 @@ class TestFinalUnusableCrop(unittest.TestCase): self.assertEqual(len(actual[3]), 3) + def test_saturated_tiny_best_skips_only_last_class0_read(self): + kwargs = {'proposals': [(.5, 0, (1400, 100, 1420, 130)), (.60, 0, (1500, 100, 1590, 237))], + 'regulatory': (False,) * 6, + 'reads': ((40, .999),) * 3 + ((55, .999),) * 3} + actual = self.run_case(**kwargs) + control = self.run_case(control=True, **kwargs) + self.assertEqual(actual[:2], control[:2]) + self.assertEqual(actual[0].speed_limit_mph, 40) + self.assertEqual(actual[0].confidence, model.DETECTOR_CLASSIFIER_RESCUE_MAX_SCORE) + self.assertEqual(len(actual[2]), 5) + self.assertEqual(len(control[2]), 6) + self.assertEqual(actual[3], control[3]) + + def test_saturated_skip_keeps_identity_veto_before_reader(self): + kwargs = {'proposals': [(.5, 0, (1400, 100, 1420, 130)), (.60, 0, (1500, 100, 1590, 237))], + 'regulatory': (False,) * 6, 'reads': ((40, .999),) * 3 + ((55, .999),) * 2, 'veto_at': 6} + actual = self.run_case(**kwargs) + control = self.run_case(control=True, **kwargs) + self.assertEqual(actual, control) + self.assertIsNone(actual[0]) + self.assertIsNone(actual[1]) + self.assertEqual(len(actual[3]), 6) + + def test_saturated_skip_counterexamples_keep_reads(self): + first = (.5, 0, (1400, 100, 1420, 130)) + last = (.60, 0, (1500, 100, 1590, 237)) + cases = ( + {'proposals': [(.4, 0, first[2]), last]}, + {'proposals': [first, last], 'custom': True}, + {'proposals': [first, last, (.3, 1, (1600, 100, 1690, 237))]}, + ) + for case in cases: + with self.subTest(case=case): + kwargs = {'regulatory': (False,) * 6, 'reads': ((40, .999),) * 3 + ((55, .999),) * 3, **case} + actual = self.run_case(**kwargs) + control = self.run_case(control=True, **kwargs) + self.assertEqual(actual, control) + self.assertEqual(len(actual[2]), 6) + + def test_saturated_skip_keeps_best_when_last_crop_advisory_rejects(self): + kwargs = {'proposals': [(.5, 0, (1400, 100, 1420, 130)), (.60, 0, (1500, 100, 1590, 237))], + 'regulatory': (False,) * 6, + 'reads': ((40, .999),) * 3 + ((55, .999),) * 2 + (None,)} + actual = self.run_case(**kwargs) + control = self.run_case(control=True, **kwargs) + self.assertEqual(actual[:2], control[:2]) + self.assertEqual(len(actual[2]), 5) + self.assertEqual(len(control[2]), 6) + self.assertEqual(actual[3], control[3]) + + def test_saturated_skip_keeps_generator_and_school_paths(self): + proposals = [(.5, 0, (1400, 100, 1420, 130)), (.60, 0, (1500, 100, 1590, 237))] + kwargs = {'regulatory': (False,) * 6, 'reads': ((40, .999),) * 3 + ((55, .999),) * 3} + actual = self.run_case(proposals=(p for p in proposals), **kwargs) + control = self.run_case(proposals=(p for p in proposals), control=True, **kwargs) + self.assertEqual(actual, control) + self.assertEqual(len(actual[2]), 6) + kwargs = {'proposals': [proposals[0], (.60, 2, proposals[1][2])], + 'regulatory': (False,) * 6, + 'reads': ((40, .999),) * 3 + (None,) + ((55, .999),) * 3} + actual = self.run_case(**kwargs) + control = self.run_case(control=True, **kwargs) + self.assertEqual(actual, control) + + if __name__ == '__main__': unittest.main() diff --git a/prebuilt.json b/prebuilt.json index eb2df993a4..f525fa8ffd 100644 --- a/prebuilt.json +++ b/prebuilt.json @@ -1 +1 @@ -{"protected_inventory_sha256": "57187556cc12a30b76ae547251cef975afa48e4c93a9a155e317c7c4c792ccb9", "schema_version": 1} +{"protected_inventory_sha256": "1e6ffb7ca4d42bc8a37087a4e0984e847bb03682ff85c31be57cf0a78bd4b8bd", "schema_version": 1}