@@ -170,12 +170,7 @@ def __init__(self):
170
170
self .current_frame = None
171
171
self .annotated_frame = None
172
172
self .frame_mutex = QMutex ()
173
- self .detection_enabled = True
174
- self ._current_barcode_items = [] # Store current detection results for live overlay
175
-
176
- import time
177
- self ._last_detection_time = time .time () # Initialize with current time to prevent issues
178
-
173
+ self .detection_enabled = True
179
174
# Detection mode
180
175
self .current_detection_mode = "Barcode" # Default to barcode detection
181
176
@@ -186,9 +181,6 @@ def __init__(self):
186
181
self .frame_timer = QTimer ()
187
182
self .frame_timer .timeout .connect (self .update_frame )
188
183
189
- # Timer for processing results
190
- self .result_timer = QTimer ()
191
- self .result_timer .timeout .connect (self .process_detection_results )
192
184
193
185
# Initialize available cameras
194
186
self .update_camera_list ()
@@ -356,7 +348,6 @@ def _start_camera_background(self, camera_index):
356
348
357
349
# Start timers
358
350
self .frame_timer .start (33 ) # ~30 FPS
359
- self .result_timer .start (100 ) # Check results every 100ms
360
351
361
352
except Exception as e :
362
353
self .error_occurred .emit (f"Error in camera background startup: { e } " )
@@ -375,15 +366,13 @@ def stop_camera(self):
375
366
try :
376
367
self .camera_running = False
377
368
self .frame_timer .stop ()
378
- self .result_timer .stop ()
379
369
380
370
if self .opencv_capture :
381
371
self .opencv_capture .release ()
382
372
self .opencv_capture = None
383
373
384
374
# Clear all annotation data to prevent overlay issues
385
375
self .annotated_frame = None
386
- self ._current_barcode_items = []
387
376
388
377
self .start_stop_btn .setText ("📷 Start Camera" )
389
378
self .capture_btn .setEnabled (False )
@@ -432,11 +421,15 @@ def toggle_detection(self, enabled):
432
421
"""Toggle real-time barcode detection."""
433
422
self .detection_enabled = enabled
434
423
if not enabled :
435
- # Clear annotations immediately when detection is disabled
436
- self ._current_barcode_items = []
424
+ # Clear the result queue when detection is disabled to prevent stale overlays
425
+ try :
426
+ while not self .result_queue .empty ():
427
+ self .result_queue .get_nowait ()
428
+ except :
429
+ pass
437
430
438
431
def update_frame (self ):
439
- """Update camera frame display with proper synchronization ."""
432
+ """Update camera frame display with real-time results fetching ."""
440
433
if not self .camera_running or not self .opencv_capture :
441
434
return
442
435
@@ -460,24 +453,16 @@ def update_frame(self):
460
453
# Always start with a fresh frame copy
461
454
display_frame = frame .copy ()
462
455
463
- # Only add annotations if we have VERY recent detections to prevent ghosting
464
- if (self .detection_enabled and
465
- hasattr (self , '_current_barcode_items' ) and
466
- self ._current_barcode_items and
467
- hasattr (self , '_last_detection_time' )):
468
-
469
- import time
470
- current_time = time .time ()
471
-
472
- # Only show annotations if they're very recent (less than 0.3 seconds old)
473
- if current_time - self ._last_detection_time < 0.3 :
456
+ # Fetch latest results directly from queue for overlay drawing
457
+ if self .detection_enabled :
458
+ latest_items = self ._get_latest_detection_results ()
459
+ if latest_items :
474
460
try :
475
- display_frame = self .draw_detection_annotations (display_frame , self ._current_barcode_items )
461
+ display_frame = self .draw_detection_annotations (display_frame , latest_items )
462
+ # Emit signal with detected items for results panel
463
+ self .barcodes_detected .emit (latest_items )
476
464
except Exception as e :
477
465
pass # Fall back to clean frame if annotation fails
478
- else :
479
- # Clear old annotations if they're stale
480
- self ._current_barcode_items = []
481
466
482
467
# Convert to Qt format and display
483
468
rgb_frame = cv2 .cvtColor (display_frame , cv2 .COLOR_BGR2RGB )
@@ -499,24 +484,26 @@ def update_frame(self):
499
484
except Exception as e :
500
485
pass # Silently ignore frame update errors
501
486
502
- def process_detection_results (self ):
503
- """Process detection results and update live annotations."""
504
- import time
487
+ def _get_latest_detection_results (self ):
488
+ """Get the latest detection results directly from the queue.
505
489
506
- if not self .detection_enabled :
507
- # Clear current results when detection is disabled
508
- self ._current_barcode_items = []
509
- return
490
+ Returns:
491
+ list: Latest detection items, or empty list if no results available.
492
+ """
493
+ import time
494
+ import queue
510
495
511
- current_time = time .time ()
512
496
detected_items = []
513
497
514
- # Process all available results
498
+ # Process all available results to get the most recent ones
515
499
while not self .result_queue .empty ():
516
500
try :
517
501
captured_result = self .result_queue .get_nowait ()
518
502
519
- # Get all items from the captured result (like reference files)
503
+ # Clear previous items and use only the latest result
504
+ detected_items .clear ()
505
+
506
+ # Get all items from the captured result
520
507
items = captured_result .get_items ()
521
508
522
509
for item in items :
@@ -527,12 +514,12 @@ def process_detection_results(self):
527
514
detected_items .append (item )
528
515
529
516
elif self .current_detection_mode == "Document" :
530
- # Document detection looks for deskewed images (like document_camera.py)
517
+ # Document detection looks for deskewed images
531
518
if item_type == EnumCapturedResultItemType .CRIT_DESKEWED_IMAGE :
532
519
detected_items .append (item )
533
520
534
521
elif self .current_detection_mode == "MRZ" :
535
- # MRZ detection looks for text lines and parsed results (like mrz_camera.py)
522
+ # MRZ detection looks for text lines and parsed results
536
523
if item_type in [EnumCapturedResultItemType .CRIT_TEXT_LINE ,
537
524
EnumCapturedResultItemType .CRIT_PARSED_RESULT ]:
538
525
detected_items .append (item )
@@ -542,8 +529,7 @@ def process_detection_results(self):
542
529
except Exception as e :
543
530
continue
544
531
545
- # Finalize detection results
546
- self ._finalize_detection_results (detected_items , current_time )
532
+ return detected_items
547
533
548
534
def _is_mrz_like_text (self , text ):
549
535
"""Check if text looks like MRZ data."""
@@ -560,22 +546,6 @@ def _is_mrz_like_text(self, text):
560
546
uppercase_and_symbols = sum (1 for c in text if c .isupper () or c .isdigit () or c == '<' )
561
547
return uppercase_and_symbols / len (text ) > 0.8
562
548
563
- def _finalize_detection_results (self , detected_items , current_time ):
564
- """Finalize detection results and update display."""
565
- # ALWAYS clear previous annotations first to prevent ghosting
566
- self ._current_barcode_items = []
567
-
568
- # Update with new detections if any
569
- if detected_items :
570
- self ._current_barcode_items = detected_items
571
- self ._last_detection_time = current_time
572
- # Emit signal with detected items for results panel
573
- self .barcodes_detected .emit (detected_items )
574
- else :
575
- # Clear old annotations more aggressively (0.5 seconds instead of 1)
576
- if current_time - self ._last_detection_time > 0.5 :
577
- self ._current_barcode_items = []
578
-
579
549
def draw_detection_annotations (self , frame , detection_items ):
580
550
"""Draw detection annotations on the frame with consistent colors."""
581
551
if not detection_items :
0 commit comments