nedo-vision-worker-core 0.3.9__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/PKG-INFO +1 -1
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/__init__.py +1 -1
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/ai/FrameDrawer.py +25 -16
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/ai/VideoDebugger.py +29 -23
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/pipeline/PipelineProcessor.py +22 -43
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/util/DrawingUtils.py +4 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core.egg-info/PKG-INFO +1 -1
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/MANIFEST.in +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/README.md +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/ai/ImageDebugger.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/ai/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/callbacks/DetectionCallbackManager.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/callbacks/DetectionCallbackTypes.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/callbacks/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/cli.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/config/ConfigurationManager.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/config/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/core_service.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/database/DatabaseManager.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/database/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/detection/BaseDetector.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/detection/RFDETRDetector.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/detection/YOLODetector.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/detection/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/detection/detection_processing/DetectionProcessor.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/detection/detection_processing/HumanDetectionProcessor.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/detection/detection_processing/PPEDetectionProcessor.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/detection/detection_processing/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/doctor.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/drawing_assets/blue/inner_corner.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/drawing_assets/blue/inner_frame.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/drawing_assets/blue/line.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/drawing_assets/blue/top_left.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/drawing_assets/blue/top_right.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/drawing_assets/red/inner_corner.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/drawing_assets/red/inner_frame.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/drawing_assets/red/line.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/drawing_assets/red/top_left.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/drawing_assets/red/top_right.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/icons/boots-green.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/icons/boots-red.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/icons/gloves-green.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/icons/gloves-red.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/icons/goggles-green.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/icons/goggles-red.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/icons/helmet-green.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/icons/helmet-red.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/icons/mask-red.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/icons/vest-green.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/icons/vest-red.png +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/ai_model.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/auth.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/config.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/dataset_source.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/logs.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/ppe_detection.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/ppe_detection_label.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/restricted_area_violation.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/user.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/worker_source.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/worker_source_pipeline.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/worker_source_pipeline_config.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/worker_source_pipeline_debug.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/models/worker_source_pipeline_detection.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/pipeline/ModelManager.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/pipeline/PipelineConfigManager.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/pipeline/PipelineManager.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/pipeline/PipelinePrepocessor.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/pipeline/PipelineSyncThread.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/pipeline/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/preprocessing/ImageResizer.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/preprocessing/ImageRoi.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/preprocessing/Preprocessor.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/preprocessing/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/repositories/AIModelRepository.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/repositories/BaseRepository.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/repositories/PPEDetectionRepository.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/repositories/RestrictedAreaRepository.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/repositories/WorkerSourcePipelineDebugRepository.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/repositories/WorkerSourcePipelineDetectionRepository.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/repositories/WorkerSourcePipelineRepository.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/repositories/WorkerSourceRepository.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/repositories/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/services/SharedVideoStreamServer.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/services/VideoSharingDaemon.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/services/VideoSharingDaemonManager.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/streams/RTMPStreamer.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/streams/SharedVideoDeviceManager.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/streams/StreamSyncThread.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/streams/VideoStream.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/streams/VideoStreamManager.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/streams/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/tracker/SFSORT.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/tracker/TrackerManager.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/tracker/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/util/BoundingBoxMetrics.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/util/ModelReadinessChecker.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/util/PersonAttributeMatcher.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/util/PersonRestrictedAreaMatcher.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/util/PipelinePreviewChecker.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/util/PlatformDetector.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/util/TablePrinter.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/util/__init__.py +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core.egg-info/SOURCES.txt +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core.egg-info/dependency_links.txt +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core.egg-info/entry_points.txt +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core.egg-info/requires.txt +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core.egg-info/top_level.txt +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/pyproject.toml +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/requirements.txt +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/setup.cfg +0 -0
- {nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nedo-vision-worker-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Nedo Vision Worker Core Library for AI Vision Processing
|
|
5
5
|
Author-email: Willy Achmat Fauzi <willy.achmat@gmail.com>
|
|
6
6
|
Maintainer-email: Willy Achmat Fauzi <willy.achmat@gmail.com>
|
{nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/__init__.py
RENAMED
|
@@ -7,7 +7,7 @@ A library for running AI vision processing and detection in the Nedo Vision plat
|
|
|
7
7
|
from .core_service import CoreService
|
|
8
8
|
from .callbacks import DetectionType, CallbackTrigger, DetectionData, IntervalMetadata
|
|
9
9
|
|
|
10
|
-
__version__ = "0.
|
|
10
|
+
__version__ = "0.4.0"
|
|
11
11
|
__all__ = [
|
|
12
12
|
"CoreService",
|
|
13
13
|
"DetectionType",
|
|
@@ -3,12 +3,16 @@ import cv2
|
|
|
3
3
|
import logging
|
|
4
4
|
import os
|
|
5
5
|
from pathlib import Path
|
|
6
|
+
import threading
|
|
6
7
|
|
|
7
8
|
import numpy as np
|
|
8
9
|
from ..util.DrawingUtils import DrawingUtils
|
|
9
10
|
|
|
10
11
|
class FrameDrawer:
|
|
11
12
|
"""Handles frame processing by drawing objects, annotations, and managing icons."""
|
|
13
|
+
|
|
14
|
+
# Share the same lock as DrawingUtils for consistent locking
|
|
15
|
+
_cv_lock = DrawingUtils._cv_lock
|
|
12
16
|
|
|
13
17
|
def __init__(self):
|
|
14
18
|
self.icons = {}
|
|
@@ -67,7 +71,8 @@ class FrameDrawer:
|
|
|
67
71
|
(int(x * width), int(y * height)) for (x, y) in normalized_points
|
|
68
72
|
]
|
|
69
73
|
if len(points) >= 3:
|
|
70
|
-
|
|
74
|
+
with self._cv_lock:
|
|
75
|
+
cv2.polylines(frame, [np.array(points, np.int32)], isClosed=True, color=color, thickness=2)
|
|
71
76
|
|
|
72
77
|
def draw_frame(self, frame, tracked_objects, with_trails=False, trail_length=10):
|
|
73
78
|
current_ids = set()
|
|
@@ -83,7 +88,9 @@ class FrameDrawer:
|
|
|
83
88
|
attributes = obj.get("attributes", [])
|
|
84
89
|
labels = [attr.get("label") for attr in attributes]
|
|
85
90
|
(color, flag) = self._get_color_from_labels(labels)
|
|
86
|
-
|
|
91
|
+
|
|
92
|
+
with self._cv_lock:
|
|
93
|
+
DrawingUtils.draw_bbox_info(frame, bbox, (color, flag), f"{track_id}", self.location_name, f"{obj.get('confidence', 0):.2f}")
|
|
87
94
|
|
|
88
95
|
# Trailing
|
|
89
96
|
if with_trails:
|
|
@@ -109,26 +116,28 @@ class FrameDrawer:
|
|
|
109
116
|
num_points = len(points)
|
|
110
117
|
|
|
111
118
|
# Draw faded trail
|
|
112
|
-
|
|
113
|
-
|
|
119
|
+
with self._cv_lock:
|
|
120
|
+
for i in range(1, num_points):
|
|
121
|
+
cv2.line(frame, points[i-1], points[i], color, 1)
|
|
114
122
|
|
|
115
123
|
current_ids.add(track_id)
|
|
116
124
|
|
|
117
|
-
|
|
125
|
+
with self._cv_lock:
|
|
126
|
+
DrawingUtils.draw_main_bbox(frame, bbox, (color, flag))
|
|
118
127
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
128
|
+
for attr in attributes:
|
|
129
|
+
attr_bbox = attr.get("bbox", [])
|
|
130
|
+
if len(attr_bbox) != 4:
|
|
131
|
+
continue
|
|
123
132
|
|
|
124
|
-
|
|
125
|
-
|
|
133
|
+
attr_label = attr.get("label", "")
|
|
134
|
+
DrawingUtils.draw_inner_box(frame, attr_bbox, self._get_color(attr_label))
|
|
126
135
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
136
|
+
icon_x = x1
|
|
137
|
+
for (label, icon) in self.icons.items():
|
|
138
|
+
if label in labels:
|
|
139
|
+
DrawingUtils.draw_alpha_overlay(frame, icon, icon_x, y1 - 25)
|
|
140
|
+
icon_x += 25
|
|
132
141
|
|
|
133
142
|
# Cleanup trails for objects that disappeared
|
|
134
143
|
if with_trails and hasattr(self, "trails"):
|
|
@@ -22,43 +22,49 @@ class VideoDebugger:
|
|
|
22
22
|
window_name = f"Pipeline {pipeline_id} - {worker_source_id}"
|
|
23
23
|
|
|
24
24
|
try:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
elapsed_time = time.time() - self.fps_tracker[window_name]["start_time"]
|
|
31
|
-
fps = self.fps_tracker[window_name]["frame_count"] / max(elapsed_time, 1e-5)
|
|
32
|
-
|
|
33
|
-
cv2.putText(frame, f"FPS: {fps:.2f}", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 1)
|
|
25
|
+
# Serialize ALL OpenCV operations to prevent segfaults
|
|
26
|
+
with self._cv_lock:
|
|
27
|
+
with self.lock:
|
|
28
|
+
if window_name not in self.fps_tracker:
|
|
29
|
+
self.fps_tracker[window_name] = {"start_time": time.time(), "frame_count": 0}
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
self.
|
|
31
|
+
self.fps_tracker[window_name]["frame_count"] += 1
|
|
32
|
+
elapsed_time = time.time() - self.fps_tracker[window_name]["start_time"]
|
|
33
|
+
fps = self.fps_tracker[window_name]["frame_count"] / max(elapsed_time, 1e-5)
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
if window_name not in self.windows:
|
|
36
|
+
self.windows[window_name] = True
|
|
37
|
+
|
|
38
|
+
# Make a copy to avoid modifying the original frame from multiple threads
|
|
39
|
+
display_frame = frame.copy()
|
|
40
|
+
|
|
40
41
|
try:
|
|
41
|
-
cv2.
|
|
42
|
+
cv2.putText(display_frame, f"FPS: {fps:.2f}", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 1)
|
|
43
|
+
cv2.imshow(window_name, display_frame)
|
|
42
44
|
key = cv2.waitKey(1) & 0xFF
|
|
43
45
|
|
|
44
46
|
if key == ord('q'):
|
|
45
|
-
self.
|
|
47
|
+
self._close_window_unsafe(window_name)
|
|
46
48
|
except Exception as e:
|
|
47
49
|
logging.error(f"Error displaying frame for {window_name}: {e}")
|
|
48
50
|
|
|
49
51
|
except Exception as e:
|
|
50
52
|
logging.error(f"Error in show_frame for {window_name}: {e}")
|
|
51
53
|
|
|
54
|
+
def _close_window_unsafe(self, window_name):
|
|
55
|
+
"""Close window without acquiring locks (called when already locked)."""
|
|
56
|
+
if window_name in self.windows:
|
|
57
|
+
try:
|
|
58
|
+
cv2.destroyWindow(window_name)
|
|
59
|
+
except Exception as e:
|
|
60
|
+
logging.error(f"Error closing window {window_name}: {e}")
|
|
61
|
+
del self.windows[window_name]
|
|
62
|
+
|
|
52
63
|
def close_window(self, window_name):
|
|
53
64
|
"""Close specific window."""
|
|
54
|
-
with self.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
try:
|
|
58
|
-
cv2.destroyWindow(window_name)
|
|
59
|
-
except Exception as e:
|
|
60
|
-
logging.error(f"Error closing window {window_name}: {e}")
|
|
61
|
-
del self.windows[window_name]
|
|
65
|
+
with self._cv_lock:
|
|
66
|
+
with self.lock:
|
|
67
|
+
self._close_window_unsafe(window_name)
|
|
62
68
|
|
|
63
69
|
def is_window_open(self, pipeline_id):
|
|
64
70
|
"""Check if a window is open for a given pipeline."""
|
|
@@ -176,6 +176,7 @@ class PipelineProcessor:
|
|
|
176
176
|
|
|
177
177
|
target_render_fps = 25.0
|
|
178
178
|
target_frame_time = 1.0 / target_render_fps
|
|
179
|
+
last_preview_check = 0
|
|
179
180
|
|
|
180
181
|
try:
|
|
181
182
|
while self.running:
|
|
@@ -186,22 +187,24 @@ class PipelineProcessor:
|
|
|
186
187
|
if frame is None:
|
|
187
188
|
if not self._handle_frame_failure(video_manager, worker_source_id):
|
|
188
189
|
break
|
|
189
|
-
# no frame this tick—just continue (the streamer will repeat last good frame)
|
|
190
190
|
time.sleep(0.04)
|
|
191
191
|
continue
|
|
192
192
|
|
|
193
|
-
# successful frame
|
|
194
193
|
self.consecutive_frame_failures = 0
|
|
195
|
-
self.last_successful_frame_time =
|
|
194
|
+
self.last_successful_frame_time = loop_start
|
|
196
195
|
self.frame_counter += 1
|
|
197
196
|
|
|
198
|
-
|
|
197
|
+
# Check preview status less frequently
|
|
198
|
+
if loop_start - last_preview_check >= self.preview_check_interval:
|
|
199
|
+
self._check_and_update_rtmp_streaming()
|
|
200
|
+
last_preview_check = loop_start
|
|
201
|
+
|
|
202
|
+
should_draw = self.rtmp_streaming_active or self.debug_flag
|
|
199
203
|
|
|
200
204
|
if should_draw:
|
|
201
|
-
# draw annotations
|
|
202
205
|
try:
|
|
203
|
-
|
|
204
|
-
|
|
206
|
+
frame_to_draw = frame.copy()
|
|
207
|
+
self.frame_drawer.draw_polygons(frame_to_draw)
|
|
205
208
|
drawn_frame = self.frame_drawer.draw_frame(
|
|
206
209
|
frame_to_draw,
|
|
207
210
|
self.tracked_objects_render,
|
|
@@ -214,26 +217,19 @@ class PipelineProcessor:
|
|
|
214
217
|
else:
|
|
215
218
|
drawn_frame = frame
|
|
216
219
|
|
|
217
|
-
# debug snapshot if requested
|
|
218
220
|
if self.debug_flag:
|
|
219
221
|
tracked_objects_render = self._process_frame(frame)
|
|
220
222
|
try:
|
|
223
|
+
debug_frame = frame.copy()
|
|
221
224
|
self.debug_repo.update_debug_entries_by_pipeline_id(
|
|
222
225
|
self.pipeline_id,
|
|
223
|
-
self.frame_drawer.draw_frame(
|
|
226
|
+
self.frame_drawer.draw_frame(debug_frame, tracked_objects_render),
|
|
224
227
|
tracked_objects_render
|
|
225
228
|
)
|
|
226
229
|
except Exception as e:
|
|
227
230
|
logging.warning(f"Debug save failed: {e}")
|
|
228
231
|
self.debug_flag = False
|
|
229
232
|
|
|
230
|
-
# Check if RTMP streaming should be active based on preview requests
|
|
231
|
-
current_time = time.time()
|
|
232
|
-
if current_time - self.last_preview_check_time >= self.preview_check_interval:
|
|
233
|
-
self._check_and_update_rtmp_streaming()
|
|
234
|
-
self.last_preview_check_time = current_time
|
|
235
|
-
|
|
236
|
-
# Push frame to RTMP stream if preview is active
|
|
237
233
|
if self.rtmp_streaming_active:
|
|
238
234
|
if self.rtmp_streamer is None:
|
|
239
235
|
try:
|
|
@@ -254,35 +250,18 @@ class PipelineProcessor:
|
|
|
254
250
|
except Exception:
|
|
255
251
|
pass
|
|
256
252
|
self.rtmp_streamer = None
|
|
257
|
-
|
|
258
|
-
# Stop RTMP streaming if preview is no longer active
|
|
259
|
-
if self.rtmp_streamer is not None:
|
|
260
|
-
try:
|
|
261
|
-
logging.info(f"🛑 Stopping RTMP streamer for pipeline {pipeline_id} (preview expired)")
|
|
262
|
-
self.rtmp_streamer.stop_stream()
|
|
263
|
-
except Exception as e:
|
|
264
|
-
logging.error(f"❌ Error stopping RTMP streamer: {e}")
|
|
265
|
-
finally:
|
|
266
|
-
self.rtmp_streamer = None
|
|
267
|
-
|
|
268
|
-
# feed detection worker with latest-only behavior
|
|
269
|
-
if self.detection_thread and self.detection_thread.is_alive():
|
|
253
|
+
elif self.rtmp_streamer is not None:
|
|
270
254
|
try:
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
try:
|
|
278
|
-
self.frame_queue.put_nowait(frame)
|
|
279
|
-
except queue.Full:
|
|
280
|
-
pass
|
|
255
|
+
logging.info(f"🛑 Stopping RTMP streamer for pipeline {pipeline_id} (preview expired)")
|
|
256
|
+
self.rtmp_streamer.stop_stream()
|
|
257
|
+
except Exception as e:
|
|
258
|
+
logging.error(f"❌ Error stopping RTMP streamer: {e}")
|
|
259
|
+
finally:
|
|
260
|
+
self.rtmp_streamer = None
|
|
281
261
|
|
|
282
|
-
try
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
logging.error(f"⚠️ Failed to render frame for pipeline {pipeline_id}: {e}")
|
|
262
|
+
# Simplified queue feeding - avoid expensive try-except
|
|
263
|
+
if not self.frame_queue.full():
|
|
264
|
+
self.frame_queue.put_nowait(frame)
|
|
286
265
|
|
|
287
266
|
loop_elapsed = time.time() - loop_start
|
|
288
267
|
sleep_time = max(0.001, target_frame_time - loop_elapsed)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nedo-vision-worker-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Nedo Vision Worker Core Library for AI Vision Processing
|
|
5
5
|
Author-email: Willy Achmat Fauzi <willy.achmat@gmail.com>
|
|
6
6
|
Maintainer-email: Willy Achmat Fauzi <willy.achmat@gmail.com>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/cli.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nedo_vision_worker_core-0.3.9 → nedo_vision_worker_core-0.4.0}/nedo_vision_worker_core/doctor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|