Detection Worker
app.infrastructure.detection.worker.detection_workerBackground YOLO detection worker — thread-safe batch frame inference.
See Also
DetectionExecutionService— coordinates detection executionVideoReader— supplies frames for inference
Layer: Infrastructure. Context: Implements concrete processing and I/O behind application-facing contracts.
DetectionWorker
Bases: QThread
Background QThread that runs YOLO inference on all video frames, emitting batches asynchronously.
| ATTRIBUTE | DESCRIPTION |
|---|---|
_s_id |
Session ID for batch routing.
TYPE:
|
_video_path |
Video path extracted from
TYPE:
|
_detection_engine |
YOLO model wrapper used for inference.
TYPE:
|
_detections_by_frame_index |
Thread-safe cache
protected by
TYPE:
|
_mutex |
Guards base detection view_state.
TYPE:
|
_stop_requested |
True when shutdown is requested.
TYPE:
|
_is_complete |
True after the full stream is processed.
TYPE:
|
Note
Signals emitted by this worker: progress_updated(frame_idx, total_frames): Emitted per frame for UI sync. batch_ready(s_id, batch): Emitted every 30 frames. finished_processing(): Emitted when the thread exits. error_occurred(msg): Emitted on exception.
Thread lifecycle: start() triggers the native QThread lifecycle,
run() loops and emits, stop() sets _stop_requested, and
finished_processing() is emitted when the thread exits.
Batch emission: accumulate detections in current_batch until it reaches 30
frames, emit batch_ready(), then reset. Remaining frames are flushed at
stream end.
Thread affinity: do not access UI from run(). Only emit signals.
Callers must use moveToThread(worker) before starting.
Shutdown sequence: worker.stop() -> worker.quit() -> worker.wait()
-> deleteLater().
Example
worker = DetectionWorker(s_id, engine) thread = QThread() worker.moveToThread(thread) worker.batch_ready.connect(on_batch_ready) worker.finished_processing.connect(thread.quit) thread.start() worker.start()
| PARAMETER | DESCRIPTION |
|---|---|
s_id
|
Identifier of the session associated with this object.
TYPE:
|
detection_engine
|
Detection engine used to process video frames.
TYPE:
|
parent
|
Optional Qt parent object.
TYPE:
|
batch_ready = Signal(object, object, float)
class-attribute
instance-attribute
error_occurred = Signal(str)
class-attribute
instance-attribute
finished_processing = Signal()
class-attribute
instance-attribute
progress_updated = Signal(int, int, float)
class-attribute
instance-attribute
__init__(s_id: SessionId, detection_engine: DetectionEngineInterface, parent: QObject | None = None) -> None
get_all_detections() -> dict[int, list[DetectionResult]]
Return copy of all cached detections (thread-safe via _mutex).
| RETURNS | DESCRIPTION |
|---|---|
dict[int, list[DetectionResult]]
|
New mapping of frame indices to new detection lists. |
get_detections(frame_index: int) -> list[DetectionResult] | None
Retrieve cached detections for frame_index, or None if not yet processed.
| PARAMETER | DESCRIPTION |
|---|---|
frame_index
|
Zero-based index of the frame to query.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[DetectionResult] | None
|
A new list of detections for the frame, or |
isRunning() -> bool
Return True if thread is currently processing frames.
| RETURNS | DESCRIPTION |
|---|---|
bool
|
|
is_complete() -> bool
Return True if stream reached end (all frames processed).
| RETURNS | DESCRIPTION |
|---|---|
bool
|
|
run() -> None
Main thread loop — read all frames, run YOLO inference, emit batches (30 frames).
Note
Workflow:
1. Open VideoReader for _video_path.
2. The first sequential read is index zero; loop: read frame, call _detection_engine.detect(), and store the
result in the cache and current batch.
3. Every 30 frames, emit batch_ready(s_id, batch) and reset the batch.
4. On stream end, flush any remaining batch.
5. On exception, emit error_occurred(msg).
6. Finally, close the reader and emit finished_processing().
Do not access UI from this thread. Only emit signals.
progress_updated() is used to synchronize UI progress.
| RAISES | DESCRIPTION |
|---|---|
None
|
Worker failures are reported through |
Example
worker.start()
start(priority: QThread.Priority = QThread.Priority.InheritPriority) -> None
Start the detection thread (calls run() in background).
| PARAMETER | DESCRIPTION |
|---|---|
priority
|
Qt thread scheduling priority passed to
TYPE:
|
stop() -> None
Request thread to stop (sets _stop_requested flag).