feat: add bounded crop evidence and keyed gallery cache

This commit is contained in:
kiyo9w 2026-09-28 15:49:34 +09:00
parent 69de9ea418
commit 0d0e9f82b9
8 changed files with 1065 additions and 41 deletions

View file

@ -502,5 +502,179 @@ class ClassificationBudgetTests(unittest.TestCase):
engine.shutdown()
class SmallBoxDetector(FakeDetector):
"""A facing too small for the frame crop to decide, so only a crop can."""
def __init__(self, box=None):
super().__init__()
self.boxes = [{
"id": 0, "box": list(box or [100, 100, 130, 200]), "confidence": 0.9,
"class_id": 0, "width": 30, "height": 100, "center": [115, 150],
}]
def make_crop_session(matcher=None, settings=None, detector=None):
detector = detector or SmallBoxDetector()
engine = RecognitionEngine(
detector, matcher or FakeMatcher(), FakeInventory(),
settings=__import__("engine").EngineSettings(classify_workers=2),
)
session = LiveSession("crop", engine, settings=settings or LiveSettings(method="hybrid"))
session.refresh_catalog()
session.enable_crops()
return session, engine, detector
def requested_crop(result):
for track in result["tracks"]:
if "crop_request" in track:
return track["crop_request"]
return None
class CropLaneTests(unittest.TestCase):
"""A full-resolution crop is extra evidence for one track, nothing else."""
def test_a_protocol_v1_client_is_never_asked(self):
session, engine, _ = make_crop_session()
session.enable_crops # noqa: B018 - documents that crops start disabled
session.settings.crops = False
process(session, 1)
result = process(session, 2)
self.assertIsNone(requested_crop(result))
self.assertEqual(result["stats"]["crops"]["requested"], 0)
engine.shutdown()
def test_accepted_crop_labels_the_track_it_was_asked_about(self):
session, engine, _ = make_crop_session()
process(session, 1)
request = requested_crop(process(session, 2))
self.assertIsNotNone(request, "a box the frame crop cannot use must be asked about")
self.assertEqual(request["frame_id"], 2)
reply = session.submit_crop(request["request_id"], request["track_id"],
request["frame_id"], frame_bytes())
self.assertEqual(reply["type"], "crop_ack")
self.assertTrue(wait_for(lambda: process(session, 3)["stats"]["crops"]["accepted"] == 1))
engine.shutdown()
def test_the_label_says_it_was_measured_on_a_crop(self):
session, engine, _ = make_crop_session()
process(session, 1)
request = requested_crop(process(session, 2))
session.submit_crop(request["request_id"], request["track_id"],
request["frame_id"], frame_bytes())
self.assertTrue(wait_for(lambda: "crop_request" not in process(session, 3)["tracks"][0]))
labelled = [t for t in process(session, 4)["tracks"] if t["identity"]["state"] == "recognized"]
self.assertTrue(labelled, "the crop should settle the track the frame could not")
self.assertEqual(labelled[0]["identity"]["sku_id"], "sku_a")
self.assertEqual(labelled[0]["identity"]["source"], "crop")
self.assertEqual(labelled[0]["identity"]["attempts"], 1)
engine.shutdown()
def test_a_crop_can_arrive_after_the_next_frame(self):
session, engine, _ = make_crop_session()
process(session, 1)
request = requested_crop(process(session, 2))
process(session, 3)
reply = session.submit_crop(request["request_id"], request["track_id"],
request["frame_id"], frame_bytes())
self.assertEqual(reply["type"], "crop_ack")
self.assertTrue(wait_for(lambda: session._crops_accepted == 1))
engine.shutdown()
def test_a_track_is_asked_once(self):
session, engine, _ = make_crop_session()
process(session, 1)
process(session, 2)
result = process(session, 3)
self.assertIsNone(requested_crop(result), "one crop per track object")
self.assertEqual(result["stats"]["crops"]["requested"], 1)
engine.shutdown()
def test_a_crop_for_another_frame_is_refused(self):
session, engine, _ = make_crop_session()
process(session, 1)
request = requested_crop(process(session, 2))
reply = session.submit_crop(request["request_id"], request["track_id"], 999, frame_bytes())
self.assertEqual(reply["code"], "CROP_MISMATCH")
result = process(session, 3)
self.assertNotEqual(result["tracks"][0]["identity"]["state"], "recognized")
self.assertEqual(result["stats"]["crops"]["rejected"], 1)
self.assertEqual(result["stats"]["crops"]["accepted"], 0)
engine.shutdown()
def test_a_crop_for_another_track_is_refused(self):
session, engine, _ = make_crop_session()
process(session, 1)
request = requested_crop(process(session, 2))
reply = session.submit_crop(request["request_id"], request["track_id"] + 41,
request["frame_id"], frame_bytes())
self.assertEqual(reply["code"], "CROP_MISMATCH")
self.assertEqual(process(session, 3)["stats"]["crops"]["accepted"], 0)
engine.shutdown()
def test_an_oversized_crop_is_refused(self):
session, engine, _ = make_crop_session(settings=LiveSettings(max_crop_bytes=2048))
session.enable_crops(2048)
process(session, 1)
request = requested_crop(process(session, 2))
reply = session.submit_crop(request["request_id"], request["track_id"],
request["frame_id"], b"\xff\xd8" + b"\x00" * 4096)
self.assertEqual(reply["code"], "CROP_TOO_LARGE")
self.assertEqual(process(session, 3)["stats"]["crops"]["accepted"], 0)
engine.shutdown()
def test_an_undecodable_crop_is_refused(self):
session, engine, _ = make_crop_session()
process(session, 1)
request = requested_crop(process(session, 2))
reply = session.submit_crop(request["request_id"], request["track_id"],
request["frame_id"], b"not an image")
self.assertEqual(reply["code"], "CROP_UNDECODABLE")
self.assertEqual(process(session, 3)["stats"]["crops"]["accepted"], 0)
engine.shutdown()
def test_a_crop_cannot_be_replayed(self):
session, engine, _ = make_crop_session()
process(session, 1)
request = requested_crop(process(session, 2))
first = session.submit_crop(request["request_id"], request["track_id"],
request["frame_id"], frame_bytes())
self.assertEqual(first["type"], "crop_ack")
again = session.submit_crop(request["request_id"], request["track_id"],
request["frame_id"], frame_bytes())
self.assertEqual(again["code"], "CROP_UNKNOWN_REQUEST")
engine.shutdown()
def test_an_unknown_request_is_refused(self):
session, engine, _ = make_crop_session()
process(session, 1)
reply = session.submit_crop("c-nope", 1, 1, frame_bytes())
self.assertEqual(reply["code"], "CROP_UNKNOWN_REQUEST")
engine.shutdown()
def test_an_unanswered_request_expires_and_frees_the_track(self):
session, engine, _ = make_crop_session(settings=LiveSettings(crop_ttl_frames=1))
process(session, 1)
request = requested_crop(process(session, 2))
process(session, 3)
# The request was made on frame 2 with a one-frame budget, so by frame 4
# it is out of date and the track it held is free again.
result = process(session, 4)
self.assertEqual(result["stats"]["crops"]["rejected"], 1, "an unanswered request is counted")
late = session.submit_crop(request["request_id"], request["track_id"],
request["frame_id"], frame_bytes())
self.assertEqual(late["code"], "CROP_UNKNOWN_REQUEST")
engine.shutdown()
def test_the_client_states_the_smaller_crop_limit(self):
session, engine, _ = make_crop_session()
self.assertEqual(session.enable_crops(4096)["max_crop_bytes"], 4096)
self.assertEqual(session.capabilities()["crop"], True)
engine.shutdown()
if __name__ == "__main__":
unittest.main()