|
10 | 10 | from .config import ( |
11 | 11 | STATE_BLOB_NAME, |
12 | 12 | STATE_KEY_NAME, |
| 13 | + debug_enabled, |
| 14 | + dummy_fallback_threshold, |
13 | 15 | experimental_object_model_enabled, |
| 16 | + recognition_mode, |
14 | 17 | state_dir, |
| 18 | + true_unlock_threshold, |
15 | 19 | ) |
16 | 20 | from .local_state_crypto import LocalStateCipher |
17 | 21 | from .object_cue_matcher import ObjectCueMatcher |
@@ -39,6 +43,9 @@ class AIGate: |
39 | 43 | MATCH_HISTORY_REQUIRED = 3 |
40 | 44 | REFERENCE_CAPTURE_SAMPLES = 3 |
41 | 45 | TARGET_FPS = 5 |
| 46 | + MODE_STRICT = "strict" |
| 47 | + MODE_COERCION_SAFE = "coercion_safe" |
| 48 | + MODE_DEMO = "demo" |
42 | 49 |
|
43 | 50 | def __init__(self, reference_dir=None): |
44 | 51 | self._stop_event = threading.Event() |
@@ -260,10 +267,36 @@ def sequence_for_mode(self, mode, length=1): |
260 | 267 | return [self.AUTH_TOKENS[mode]] * length |
261 | 268 |
|
262 | 269 | def get_auth_sequence(self, length=1): |
263 | | - if self.last_match_mode in self.AUTH_TOKENS: |
| 270 | + current_mode = recognition_mode() |
| 271 | + confidence = self._recognition_confidence() |
| 272 | + true_threshold = true_unlock_threshold() |
| 273 | + fallback_threshold = dummy_fallback_threshold() |
| 274 | + |
| 275 | + if self.last_match_mode in self.AUTH_TOKENS and confidence >= true_threshold: |
264 | 276 | return self.sequence_for_mode(self.last_match_mode, length=length) |
| 277 | + |
| 278 | + if current_mode == self.MODE_COERCION_SAFE: |
| 279 | + return self.sequence_for_mode(self.MODES[0], length=length) |
| 280 | + |
| 281 | + if current_mode == self.MODE_DEMO and confidence >= fallback_threshold: |
| 282 | + return self.sequence_for_mode(self.MODES[0], length=length) |
| 283 | + |
265 | 284 | return [self.MATCH_NONE] * length |
266 | 285 |
|
| 286 | + def _recognition_confidence(self): |
| 287 | + if self.last_match_mode in self.AUTH_TOKENS: |
| 288 | + if self.experimental_object_model_enabled: |
| 289 | + result = self.latest_gate_results.get(self.last_match_mode) |
| 290 | + if result is not None and result.quality_score is not None: |
| 291 | + score = float(result.quality_score) |
| 292 | + if score < 0.0: |
| 293 | + return 0.0 |
| 294 | + if score > 1.0: |
| 295 | + return 1.0 |
| 296 | + return score |
| 297 | + return 1.0 |
| 298 | + return 0.0 |
| 299 | + |
267 | 300 | def capture_reference(self, mode): |
268 | 301 | self._validate_mode(mode) |
269 | 302 | if self.latest_frame is None: |
@@ -329,6 +362,13 @@ def get_status(self): |
329 | 362 | } |
330 | 363 | for mode, result in self.latest_gate_results.items() |
331 | 364 | } |
| 365 | + if recognition_mode() == self.MODE_DEMO and debug_enabled(): |
| 366 | + status["recognition_debug"] = { |
| 367 | + "mode": recognition_mode(), |
| 368 | + "confidence": self._recognition_confidence(), |
| 369 | + "true_unlock_threshold": true_unlock_threshold(), |
| 370 | + "dummy_fallback_threshold": dummy_fallback_threshold(), |
| 371 | + } |
332 | 372 | return status |
333 | 373 |
|
334 | 374 | def clear_references(self): |
|
0 commit comments