pixelflow 0.1.2__tar.gz → 0.1.3__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.
- {pixelflow-0.1.2 → pixelflow-0.1.3}/PKG-INFO +22 -17
- {pixelflow-0.1.2 → pixelflow-0.1.3}/README.md +20 -16
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/__init__.py +23 -6
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/__init__.py +5 -2
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/anchors.py +2 -2
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/box.py +3 -3
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/crossing.py +6 -6
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/filled_box.py +4 -4
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/fps_counter.py +9 -6
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/grid_overlay.py +4 -4
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/keypoint.py +3 -3
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/keypoint_skeleton.py +2 -2
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/label.py +4 -4
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/mask.py +3 -3
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/oval.py +3 -3
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/polygon.py +4 -4
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/utils.py +9 -9
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/zones.py +1 -1
- pixelflow-0.1.3/pixelflow/assets.py +364 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/buffer.py +24 -25
- pixelflow-0.1.3/pixelflow/classes.py +86 -0
- pixelflow-0.1.3/pixelflow/colors.py +100 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/detections/__init__.py +14 -29
- pixelflow-0.1.3/pixelflow/detections/converters.py +1072 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/detections/detections.py +7 -209
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/detections/filters.py +31 -345
- pixelflow-0.1.3/pixelflow/media.py +458 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/smoother.py +11 -6
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/transforms/detections.py +6 -6
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/transforms/image.py +14 -14
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow.egg-info/PKG-INFO +22 -17
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow.egg-info/SOURCES.txt +2 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow.egg-info/requires.txt +1 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pyproject.toml +3 -2
- pixelflow-0.1.2/pixelflow/colors.py +0 -100
- pixelflow-0.1.2/pixelflow/detections/converters.py +0 -2214
- pixelflow-0.1.2/pixelflow/media.py +0 -427
- {pixelflow-0.1.2 → pixelflow-0.1.3}/LICENSE +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/blur.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/dot.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/heatmap.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/motion_dots.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/motion_trails.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/pixelate.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/annotators/scale_bar.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/crossings.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/slicer.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/strategies.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/timer.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/tracker/__init__.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/tracker/bytetrack.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/tracker/kalman_filter.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/tracker/matching.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/tracker/track.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/transforms/__init__.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/transforms/inverse.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/validators.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow/zones.py +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow.egg-info/dependency_links.txt +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/pixelflow.egg-info/top_level.txt +0 -0
- {pixelflow-0.1.2 → pixelflow-0.1.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pixelflow
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Computer vision processing library for visualizing and analyzing detection results from ML models
|
|
5
5
|
Author-email: Emrah Nazif <emrah@datamarkin.com>, Datamarkin <support@datamarkin.com>
|
|
6
6
|
License: MIT
|
|
@@ -29,6 +29,7 @@ Requires-Dist: shapely>=2.0.0
|
|
|
29
29
|
Requires-Dist: numpy>=1.21.0
|
|
30
30
|
Requires-Dist: opencv-python>=4.8.0
|
|
31
31
|
Requires-Dist: scipy>=1.10.0
|
|
32
|
+
Requires-Dist: Pillow>=9.0.0
|
|
32
33
|
Provides-Extra: dev
|
|
33
34
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
34
35
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -50,12 +51,12 @@ import pixelflow as pf
|
|
|
50
51
|
from ultralytics import YOLO
|
|
51
52
|
|
|
52
53
|
model = YOLO("yolo11n.pt")
|
|
53
|
-
|
|
54
|
+
video = pf.VideoReader("traffic.mp4", width=640)
|
|
54
55
|
tracker = pf.tracker.ByteTracker()
|
|
55
56
|
zones = pf.Zones()
|
|
56
57
|
zones.add_zone([(100, 400), (500, 400), (500, 600), (100, 600)], zone_id="entrance")
|
|
57
58
|
|
|
58
|
-
for frame in
|
|
59
|
+
for frame in video:
|
|
59
60
|
detections = pf.detections.from_ultralytics(model.predict(frame))
|
|
60
61
|
detections = tracker.update(detections)
|
|
61
62
|
zones.update(detections)
|
|
@@ -64,7 +65,8 @@ for frame in media.frames:
|
|
|
64
65
|
frame = pf.annotate.label(frame, detections)
|
|
65
66
|
frame = pf.annotate.zones(frame, zones)
|
|
66
67
|
|
|
67
|
-
pf.show_frame("Live", frame)
|
|
68
|
+
if pf.show_frame("Live", frame) == ord('q'):
|
|
69
|
+
break
|
|
68
70
|
```
|
|
69
71
|
|
|
70
72
|
## Installation
|
|
@@ -139,29 +141,32 @@ english_text = detections.filter_by_text_language("en")
|
|
|
139
141
|
|
|
140
142
|
### Media Handling
|
|
141
143
|
|
|
142
|
-
|
|
144
|
+
Purpose-built classes for videos, cameras, and images:
|
|
143
145
|
|
|
144
146
|
```python
|
|
145
147
|
import pixelflow as pf
|
|
146
148
|
|
|
147
|
-
#
|
|
148
|
-
|
|
149
|
-
print(
|
|
149
|
+
# Read a video file
|
|
150
|
+
video = pf.VideoReader("video.mp4", width=640)
|
|
151
|
+
print(f"{video.width}x{video.height}, {video.fps}fps, {len(video)} frames")
|
|
150
152
|
|
|
151
|
-
for frame in
|
|
152
|
-
|
|
153
|
-
|
|
153
|
+
for frame in video: # Replayable — resets on each iteration
|
|
154
|
+
if pf.show_frame("Preview", frame) == ord('q'):
|
|
155
|
+
break
|
|
154
156
|
|
|
155
|
-
#
|
|
156
|
-
|
|
157
|
+
# Load a single image
|
|
158
|
+
image = pf.read_image("photo.jpg", width=640)
|
|
157
159
|
|
|
158
|
-
#
|
|
159
|
-
|
|
160
|
+
# Webcam / network stream
|
|
161
|
+
cam = pf.CameraStream(0, width=640)
|
|
162
|
+
cam = pf.CameraStream("rtsp://camera.local/stream")
|
|
160
163
|
|
|
161
164
|
# Write processed video
|
|
162
|
-
|
|
165
|
+
writer = pf.VideoWriter("output.mp4", fps=video.fps)
|
|
166
|
+
for frame in video:
|
|
163
167
|
processed = process(frame)
|
|
164
|
-
|
|
168
|
+
writer.write(processed)
|
|
169
|
+
writer.close()
|
|
165
170
|
```
|
|
166
171
|
|
|
167
172
|
### Zone-Based Analytics
|
|
@@ -13,12 +13,12 @@ import pixelflow as pf
|
|
|
13
13
|
from ultralytics import YOLO
|
|
14
14
|
|
|
15
15
|
model = YOLO("yolo11n.pt")
|
|
16
|
-
|
|
16
|
+
video = pf.VideoReader("traffic.mp4", width=640)
|
|
17
17
|
tracker = pf.tracker.ByteTracker()
|
|
18
18
|
zones = pf.Zones()
|
|
19
19
|
zones.add_zone([(100, 400), (500, 400), (500, 600), (100, 600)], zone_id="entrance")
|
|
20
20
|
|
|
21
|
-
for frame in
|
|
21
|
+
for frame in video:
|
|
22
22
|
detections = pf.detections.from_ultralytics(model.predict(frame))
|
|
23
23
|
detections = tracker.update(detections)
|
|
24
24
|
zones.update(detections)
|
|
@@ -27,7 +27,8 @@ for frame in media.frames:
|
|
|
27
27
|
frame = pf.annotate.label(frame, detections)
|
|
28
28
|
frame = pf.annotate.zones(frame, zones)
|
|
29
29
|
|
|
30
|
-
pf.show_frame("Live", frame)
|
|
30
|
+
if pf.show_frame("Live", frame) == ord('q'):
|
|
31
|
+
break
|
|
31
32
|
```
|
|
32
33
|
|
|
33
34
|
## Installation
|
|
@@ -102,29 +103,32 @@ english_text = detections.filter_by_text_language("en")
|
|
|
102
103
|
|
|
103
104
|
### Media Handling
|
|
104
105
|
|
|
105
|
-
|
|
106
|
+
Purpose-built classes for videos, cameras, and images:
|
|
106
107
|
|
|
107
108
|
```python
|
|
108
109
|
import pixelflow as pf
|
|
109
110
|
|
|
110
|
-
#
|
|
111
|
-
|
|
112
|
-
print(
|
|
111
|
+
# Read a video file
|
|
112
|
+
video = pf.VideoReader("video.mp4", width=640)
|
|
113
|
+
print(f"{video.width}x{video.height}, {video.fps}fps, {len(video)} frames")
|
|
113
114
|
|
|
114
|
-
for frame in
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
for frame in video: # Replayable — resets on each iteration
|
|
116
|
+
if pf.show_frame("Preview", frame) == ord('q'):
|
|
117
|
+
break
|
|
117
118
|
|
|
118
|
-
#
|
|
119
|
-
|
|
119
|
+
# Load a single image
|
|
120
|
+
image = pf.read_image("photo.jpg", width=640)
|
|
120
121
|
|
|
121
|
-
#
|
|
122
|
-
|
|
122
|
+
# Webcam / network stream
|
|
123
|
+
cam = pf.CameraStream(0, width=640)
|
|
124
|
+
cam = pf.CameraStream("rtsp://camera.local/stream")
|
|
123
125
|
|
|
124
126
|
# Write processed video
|
|
125
|
-
|
|
127
|
+
writer = pf.VideoWriter("output.mp4", fps=video.fps)
|
|
128
|
+
for frame in video:
|
|
126
129
|
processed = process(frame)
|
|
127
|
-
|
|
130
|
+
writer.write(processed)
|
|
131
|
+
writer.close()
|
|
128
132
|
```
|
|
129
133
|
|
|
130
134
|
### Zone-Based Analytics
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.3"
|
|
2
2
|
__author__ = "Datamarkin"
|
|
3
3
|
|
|
4
4
|
# Import core modules
|
|
@@ -14,9 +14,15 @@ from . import slicer
|
|
|
14
14
|
from . import smoother
|
|
15
15
|
from . import timer
|
|
16
16
|
from . import tracker
|
|
17
|
+
from . import assets
|
|
18
|
+
from .classes import COCO_CLASSES
|
|
17
19
|
|
|
18
20
|
# Import specific functions for top-level access
|
|
19
|
-
from .media import
|
|
21
|
+
from .media import (
|
|
22
|
+
DisplayExit, VideoReader, CameraStream, VideoWriter,
|
|
23
|
+
read_image, read_video, display_video, display_image, save_image,
|
|
24
|
+
close_display, to_pil, from_pil,
|
|
25
|
+
)
|
|
20
26
|
from .zones import Zones
|
|
21
27
|
from .crossings import Crossings
|
|
22
28
|
from .slicer import SlicedInference, auto_slice_size
|
|
@@ -38,11 +44,18 @@ __all__ = [
|
|
|
38
44
|
|
|
39
45
|
# Media handling
|
|
40
46
|
"media",
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
47
|
+
"DisplayExit",
|
|
48
|
+
"VideoReader",
|
|
49
|
+
"CameraStream",
|
|
50
|
+
"VideoWriter",
|
|
51
|
+
"read_image",
|
|
52
|
+
"read_video",
|
|
53
|
+
"display_video",
|
|
54
|
+
"display_image",
|
|
55
|
+
"save_image",
|
|
45
56
|
"close_display",
|
|
57
|
+
"to_pil",
|
|
58
|
+
"from_pil",
|
|
46
59
|
|
|
47
60
|
# Spatial analysis
|
|
48
61
|
"zones",
|
|
@@ -51,6 +64,7 @@ __all__ = [
|
|
|
51
64
|
"Crossings",
|
|
52
65
|
|
|
53
66
|
# Processing utilities
|
|
67
|
+
"assets",
|
|
54
68
|
"slicer",
|
|
55
69
|
"SlicedInference",
|
|
56
70
|
"auto_slice_size",
|
|
@@ -62,6 +76,9 @@ __all__ = [
|
|
|
62
76
|
"TimeTracker",
|
|
63
77
|
"tracker",
|
|
64
78
|
|
|
79
|
+
# Constants
|
|
80
|
+
"COCO_CLASSES",
|
|
81
|
+
|
|
65
82
|
# Metadata
|
|
66
83
|
"__version__",
|
|
67
84
|
"__author__"
|
|
@@ -23,7 +23,7 @@ from .zones import zones
|
|
|
23
23
|
# TODO: Import these once implemented
|
|
24
24
|
from .filled_box import filled_box
|
|
25
25
|
# from .dot import dot
|
|
26
|
-
|
|
26
|
+
from .fps_counter import fps_counter
|
|
27
27
|
from .grid_overlay import grid_overlay
|
|
28
28
|
# from .heatmap import heatmap
|
|
29
29
|
from .keypoint import keypoint
|
|
@@ -56,5 +56,8 @@ __all__ = [
|
|
|
56
56
|
|
|
57
57
|
# Zone annotators
|
|
58
58
|
'zones',
|
|
59
|
-
'crossings'
|
|
59
|
+
'crossings',
|
|
60
|
+
|
|
61
|
+
# Overlay annotators
|
|
62
|
+
'fps_counter',
|
|
60
63
|
]
|
|
@@ -38,7 +38,7 @@ def anchors(
|
|
|
38
38
|
Supports drawing individual anchor points or multiple points simultaneously.
|
|
39
39
|
|
|
40
40
|
Args:
|
|
41
|
-
image (np.ndarray): Input image to draw anchor points on in
|
|
41
|
+
image (np.ndarray): Input image to draw anchor points on in RGB format.
|
|
42
42
|
Image is modified in-place.
|
|
43
43
|
detections (Detections): Detection results containing bounding boxes.
|
|
44
44
|
Each detection must have a 'bbox' attribute with (x1, y1, x2, y2) coordinates.
|
|
@@ -51,7 +51,7 @@ def anchors(
|
|
|
51
51
|
thickness (Optional[int]): Thickness of circle outline in pixels.
|
|
52
52
|
Use -1 for filled circles.
|
|
53
53
|
If None, defaults to -1 (filled).
|
|
54
|
-
colors (Optional[List[tuple]]): List of
|
|
54
|
+
colors (Optional[List[tuple]]): List of RGB color tuples for custom colors.
|
|
55
55
|
Colors mapped to unique class_ids in order of appearance.
|
|
56
56
|
If None, uses default ColorManager colors.
|
|
57
57
|
|
|
@@ -22,13 +22,13 @@ def box(
|
|
|
22
22
|
Automatically adapts line thickness based on image dimensions for optimal visibility.
|
|
23
23
|
|
|
24
24
|
Args:
|
|
25
|
-
image (np.ndarray): Input image to draw boxes on (
|
|
25
|
+
image (np.ndarray): Input image to draw boxes on (RGB format).
|
|
26
26
|
Modified in-place with drawn bounding boxes.
|
|
27
27
|
detections (Detections): Detections object containing bounding boxes.
|
|
28
28
|
Each detection must have a 'bbox' attribute with (x1, y1, x2, y2) coordinates.
|
|
29
29
|
thickness (Optional[int]): Line thickness for bounding boxes in pixels.
|
|
30
30
|
If None, automatically determined based on image size.
|
|
31
|
-
colors (Optional[List[tuple]]): List of
|
|
31
|
+
colors (Optional[List[tuple]]): List of RGB color tuples to override default colors.
|
|
32
32
|
Colors are mapped to unique class_ids in order of appearance.
|
|
33
33
|
If None, uses default ColorManager colors.
|
|
34
34
|
|
|
@@ -54,7 +54,7 @@ def box(
|
|
|
54
54
|
>>> annotated = pf.annotators.box(image, detections)
|
|
55
55
|
>>>
|
|
56
56
|
>>> # Override with custom colors for specific classes
|
|
57
|
-
>>> custom_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] #
|
|
57
|
+
>>> custom_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] # Red, Green, Blue
|
|
58
58
|
>>> annotated = pf.annotators.box(image, detections, colors=custom_colors)
|
|
59
59
|
>>>
|
|
60
60
|
>>> # Use custom thickness for fine control
|
|
@@ -29,18 +29,18 @@ def crossing(
|
|
|
29
29
|
The annotation adapts automatically to image resolution for optimal visibility.
|
|
30
30
|
|
|
31
31
|
Args:
|
|
32
|
-
image (np.ndarray): Input
|
|
32
|
+
image (np.ndarray): Input RGB image to annotate. Must be a 3-channel NumPy array
|
|
33
33
|
with shape (height, width, 3).
|
|
34
34
|
crossing_line: Crossing object from pixelflow.crossings containing line geometry,
|
|
35
35
|
counts, and color. Must have attributes: start, end, color,
|
|
36
36
|
in_count, out_count.
|
|
37
37
|
thickness (Optional[int]): Line thickness in pixels. If None, uses adaptive
|
|
38
38
|
sizing based on image resolution. Range: [1, ∞].
|
|
39
|
-
color (Optional[Tuple[int, int, int]]): Line color as
|
|
39
|
+
color (Optional[Tuple[int, int, int]]): Line color as RGB tuple (0-255 each).
|
|
40
40
|
If None, uses crossing_line.color.
|
|
41
41
|
text_thickness (Optional[int]): Text stroke thickness in pixels. If None,
|
|
42
42
|
uses adaptive sizing. Range: [1, ∞].
|
|
43
|
-
text_color (Optional[Tuple[int, int, int]]): Text color as
|
|
43
|
+
text_color (Optional[Tuple[int, int, int]]): Text color as RGB tuple (0-255 each).
|
|
44
44
|
Default is white (255, 255, 255).
|
|
45
45
|
text_scale (Optional[float]): Text scale factor. If None, uses adaptive sizing.
|
|
46
46
|
Range: (0, ∞). Default ~0.5.
|
|
@@ -146,7 +146,7 @@ def crossing(
|
|
|
146
146
|
start_point = tuple(map(int, crossing_line.start))
|
|
147
147
|
end_point = tuple(map(int, crossing_line.end))
|
|
148
148
|
cv2.line(image, start_point, end_point, crossing_color, thickness, cv2.LINE_AA)
|
|
149
|
-
|
|
149
|
+
|
|
150
150
|
# Draw end point markers (scale with image size)
|
|
151
151
|
marker_size = max(3, int(params['thickness'] * 2.5))
|
|
152
152
|
cv2.circle(image, start_point, marker_size, text_color, -1, cv2.LINE_AA)
|
|
@@ -191,7 +191,7 @@ def crossing(
|
|
|
191
191
|
bg_x2 = text_x + text_width + text_padding
|
|
192
192
|
bg_y2 = text_y + text_padding
|
|
193
193
|
cv2.rectangle(image, (bg_x1, bg_y1), (bg_x2, bg_y2), crossing_color, -1)
|
|
194
|
-
|
|
194
|
+
|
|
195
195
|
# Draw text
|
|
196
196
|
cv2.putText(
|
|
197
197
|
image, text, (text_x, text_y),
|
|
@@ -211,7 +211,7 @@ def crossings(image: np.ndarray, crossings_manager) -> np.ndarray:
|
|
|
211
211
|
information using the crossing() function.
|
|
212
212
|
|
|
213
213
|
Args:
|
|
214
|
-
image (np.ndarray): Input
|
|
214
|
+
image (np.ndarray): Input RGB image to annotate. Must be a 3-channel NumPy array
|
|
215
215
|
with shape (height, width, 3).
|
|
216
216
|
crossings_manager: Crossings manager object containing multiple crossing lines.
|
|
217
217
|
Must have a 'crossings' attribute that is iterable,
|
|
@@ -23,7 +23,7 @@ def filled_box(
|
|
|
23
23
|
dimensions for optimal visibility and uses alpha blending for professional-quality results.
|
|
24
24
|
|
|
25
25
|
Args:
|
|
26
|
-
image (np.ndarray): Input image to draw filled boxes on in
|
|
26
|
+
image (np.ndarray): Input image to draw filled boxes on in RGB color format.
|
|
27
27
|
Expected shape: (height, width, 3) with uint8 values [0, 255].
|
|
28
28
|
detections (Detections): Detections object containing bounding boxes.
|
|
29
29
|
Each detection must have a 'bbox' attribute with (x1, y1, x2, y2)
|
|
@@ -33,8 +33,8 @@ def filled_box(
|
|
|
33
33
|
Range: [0.0, 1.0] where 0.0 is fully transparent and 1.0 is opaque.
|
|
34
34
|
Values outside this range are automatically clamped.
|
|
35
35
|
If None, automatically calculated based on image size (typically 0.3-0.5).
|
|
36
|
-
colors (Optional[List[tuple]]): List of
|
|
37
|
-
Each tuple should contain (
|
|
36
|
+
colors (Optional[List[tuple]]): List of RGB color tuples to override default colors.
|
|
37
|
+
Each tuple should contain (R, G, B) values in range [0, 255].
|
|
38
38
|
Colors are mapped to unique class_ids in order of appearance.
|
|
39
39
|
If None, uses default ColorManager colors based on class_id.
|
|
40
40
|
|
|
@@ -66,7 +66,7 @@ def filled_box(
|
|
|
66
66
|
>>> annotated = pf.annotate.filled_box(image, detections, opacity=0.25)
|
|
67
67
|
>>>
|
|
68
68
|
>>> # Override with custom colors for specific visualization needs
|
|
69
|
-
>>> custom_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] #
|
|
69
|
+
>>> custom_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] # Red, Green, Blue
|
|
70
70
|
>>> annotated = pf.annotate.filled_box(image, detections, opacity=0.4, colors=custom_colors)
|
|
71
71
|
>>>
|
|
72
72
|
>>> # High opacity for maximum emphasis in presentations
|
|
@@ -32,12 +32,15 @@ def fps_counter(image: np.ndarray, detections: 'Detections', thickness=None):
|
|
|
32
32
|
else:
|
|
33
33
|
font_scale = 1
|
|
34
34
|
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
# Compute adaptive position based on image dimensions
|
|
36
|
+
params = _get_adaptive_params(image)
|
|
37
|
+
padding = params['padding']
|
|
38
|
+
text_size = cv2.getTextSize(f"FPS: 000", cv2.FONT_HERSHEY_SIMPLEX, font_scale, thickness)[0]
|
|
39
|
+
position = (padding, padding + text_size[1])
|
|
40
|
+
|
|
41
|
+
# Draw FPS text in green (RGB)
|
|
42
|
+
fps_color = (0, 255, 0)
|
|
40
43
|
fps_text = f"FPS: {int(fps_counter.fps)}"
|
|
41
|
-
cv2.putText(image, fps_text,
|
|
44
|
+
cv2.putText(image, fps_text, position, cv2.FONT_HERSHEY_SIMPLEX, font_scale, fps_color, thickness)
|
|
42
45
|
|
|
43
46
|
return image
|
|
@@ -26,7 +26,7 @@ def grid_overlay(
|
|
|
26
26
|
Can create filled checkerboard patterns for visual segmentation.
|
|
27
27
|
|
|
28
28
|
Args:
|
|
29
|
-
image (np.ndarray): Input image to draw grid overlays on. Must be in
|
|
29
|
+
image (np.ndarray): Input image to draw grid overlays on. Must be in RGB format
|
|
30
30
|
with shape (H, W, 3) and dtype uint8.
|
|
31
31
|
detections (Detections): Detections object containing bounding boxes.
|
|
32
32
|
Each detection must have a 'bbox' attribute with (x1, y1, x2, y2) coordinates
|
|
@@ -38,7 +38,7 @@ def grid_overlay(
|
|
|
38
38
|
thickness (Optional[int]): Line thickness for grid lines in pixels.
|
|
39
39
|
If None, automatically determined based on image size (typically 1-3).
|
|
40
40
|
Range: Must be >= 1. Values > 10 may cause visual overlap.
|
|
41
|
-
colors (Optional[List[tuple]]): List of
|
|
41
|
+
colors (Optional[List[tuple]]): List of RGB color tuples to override default colors.
|
|
42
42
|
Each tuple must be 3 integers in range [0, 255].
|
|
43
43
|
Colors are mapped to unique class_ids in order of appearance.
|
|
44
44
|
If None, uses default ColorManager colors.
|
|
@@ -151,7 +151,7 @@ def grid_overlay(
|
|
|
151
151
|
cell_x2 = int(x1 + (col + 1) * cell_width)
|
|
152
152
|
cell_y2 = int(y1 + (row + 1) * cell_height)
|
|
153
153
|
|
|
154
|
-
cv2.rectangle(overlay, (cell_x1, cell_y1), (cell_x2, cell_y2),
|
|
154
|
+
cv2.rectangle(overlay, (cell_x1, cell_y1), (cell_x2, cell_y2),
|
|
155
155
|
color, thickness=cv2.FILLED)
|
|
156
156
|
|
|
157
157
|
# Blend overlay with original image
|
|
@@ -161,7 +161,7 @@ def grid_overlay(
|
|
|
161
161
|
for i in range(1, cols):
|
|
162
162
|
x_pos = int(x1 + (width * i / cols))
|
|
163
163
|
cv2.line(image, (x_pos, y1), (x_pos, y2), color=color, thickness=thickness)
|
|
164
|
-
|
|
164
|
+
|
|
165
165
|
# Draw horizontal grid lines
|
|
166
166
|
for i in range(1, rows):
|
|
167
167
|
y_pos = int(y1 + (height * i / rows))
|
|
@@ -26,7 +26,7 @@ def keypoint(
|
|
|
26
26
|
point annotations.
|
|
27
27
|
|
|
28
28
|
Args:
|
|
29
|
-
image (np.ndarray): Input image to draw keypoints on (
|
|
29
|
+
image (np.ndarray): Input image to draw keypoints on (RGB format).
|
|
30
30
|
Modified in-place with drawn keypoint markers.
|
|
31
31
|
detections (Detections): Detections object containing keypoints.
|
|
32
32
|
Each detection may have a 'keypoints' attribute with
|
|
@@ -36,7 +36,7 @@ def keypoint(
|
|
|
36
36
|
thickness (Optional[int]): Thickness of circle outline in pixels.
|
|
37
37
|
Use -1 for filled circles (default).
|
|
38
38
|
If None, defaults to -1 (filled).
|
|
39
|
-
colors (Optional[List[tuple]]): List of
|
|
39
|
+
colors (Optional[List[tuple]]): List of RGB color tuples for custom colors.
|
|
40
40
|
Colors mapped to unique class_ids in order.
|
|
41
41
|
If None, uses default ColorManager colors.
|
|
42
42
|
show_names (bool): If True, draws keypoint names as text labels next to points.
|
|
@@ -67,7 +67,7 @@ def keypoint(
|
|
|
67
67
|
... image, detections,
|
|
68
68
|
... radius=5,
|
|
69
69
|
... thickness=2,
|
|
70
|
-
... colors=[(0, 255, 0)], # Green
|
|
70
|
+
... colors=[(0, 255, 0)], # Green (RGB)
|
|
71
71
|
... show_names=True
|
|
72
72
|
... )
|
|
73
73
|
>>>
|
|
@@ -50,7 +50,7 @@ def keypoint_skeleton(
|
|
|
50
50
|
body structure, wing structure, or any connected landmark system.
|
|
51
51
|
|
|
52
52
|
Args:
|
|
53
|
-
image (np.ndarray): Input image to draw skeleton on (
|
|
53
|
+
image (np.ndarray): Input image to draw skeleton on (RGB format).
|
|
54
54
|
Modified in-place with drawn skeleton lines.
|
|
55
55
|
detections (Detections): Detections object containing keypoints.
|
|
56
56
|
Each detection may have a 'keypoints' attribute with
|
|
@@ -61,7 +61,7 @@ def keypoint_skeleton(
|
|
|
61
61
|
If None, uses COCO human pose skeleton.
|
|
62
62
|
thickness (Optional[int]): Line thickness for skeleton connections in pixels.
|
|
63
63
|
If None, automatically determined based on image size.
|
|
64
|
-
colors (Optional[List[tuple]]): List of
|
|
64
|
+
colors (Optional[List[tuple]]): List of RGB color tuples for custom colors.
|
|
65
65
|
Colors mapped to unique class_ids in order.
|
|
66
66
|
If None, uses default ColorManager colors.
|
|
67
67
|
|
|
@@ -29,7 +29,7 @@ def label(
|
|
|
29
29
|
|
|
30
30
|
Args:
|
|
31
31
|
image (np.ndarray): Input image to annotate. Must be a valid OpenCV image array
|
|
32
|
-
in
|
|
32
|
+
in RGB format with shape (H, W, 3) or (H, W).
|
|
33
33
|
detections (Detections): PixelFlow detections object containing bounding box
|
|
34
34
|
coordinates and optional attributes (class_name, confidence,
|
|
35
35
|
class_id, tracker_id).
|
|
@@ -48,10 +48,10 @@ def label(
|
|
|
48
48
|
Range: [0, 50]. Default is 6.
|
|
49
49
|
line_spacing (int): Additional spacing in pixels between lines for multi-line text.
|
|
50
50
|
Range: [0, 20]. Default is 2.
|
|
51
|
-
bg_color (Optional[Union[tuple, str]]): Background rectangle color in
|
|
51
|
+
bg_color (Optional[Union[tuple, str]]): Background rectangle color in RGB format.
|
|
52
52
|
If None, uses automatic color based on class_id.
|
|
53
|
-
Can be tuple (
|
|
54
|
-
text_color (tuple): Text color in
|
|
53
|
+
Can be tuple (R, G, B) or color string.
|
|
54
|
+
text_color (tuple): Text color in RGB format. Default is white (255, 255, 255).
|
|
55
55
|
|
|
56
56
|
Returns:
|
|
57
57
|
np.ndarray: Input image with labels drawn directly on it (in-place modification).
|
|
@@ -22,7 +22,7 @@ def mask(
|
|
|
22
22
|
lists, with automatic format detection and conversion for seamless integration.
|
|
23
23
|
|
|
24
24
|
Args:
|
|
25
|
-
frame (np.ndarray): Input video frame in
|
|
25
|
+
frame (np.ndarray): Input video frame in RGB format (height, width, 3).
|
|
26
26
|
Modified in-place with overlaid masks.
|
|
27
27
|
detections (Detections): Detections object containing mask data.
|
|
28
28
|
Each detection's masks attribute can contain binary arrays
|
|
@@ -30,7 +30,7 @@ def mask(
|
|
|
30
30
|
opacity (float): Opacity level for blending masks with the frame.
|
|
31
31
|
Range: [0.0, 1.0]. Default is 0.5 (semi-transparent).
|
|
32
32
|
Value of 1.0 creates opaque masks, 0.0 makes them invisible.
|
|
33
|
-
colors (Optional[List[tuple]]): List of
|
|
33
|
+
colors (Optional[List[tuple]]): List of RGB color tuples to override default colors.
|
|
34
34
|
Colors are mapped to unique class_ids in order of appearance.
|
|
35
35
|
If None, uses default ColorManager colors.
|
|
36
36
|
|
|
@@ -57,7 +57,7 @@ def mask(
|
|
|
57
57
|
>>> annotated = pf.annotators.mask(image, detections)
|
|
58
58
|
>>>
|
|
59
59
|
>>> # Use custom colors for specific classes
|
|
60
|
-
>>> custom_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] #
|
|
60
|
+
>>> custom_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] # Red, Green, Blue
|
|
61
61
|
>>> annotated = pf.annotators.mask(image, detections, colors=custom_colors)
|
|
62
62
|
>>>
|
|
63
63
|
>>> # Create opaque masks for clear segmentation boundaries
|
|
@@ -26,7 +26,7 @@ def oval(
|
|
|
26
26
|
effects, and ground-based tracking visualizations.
|
|
27
27
|
|
|
28
28
|
Args:
|
|
29
|
-
image (np.ndarray): Input image array with shape (H, W, 3) in
|
|
29
|
+
image (np.ndarray): Input image array with shape (H, W, 3) in RGB color format.
|
|
30
30
|
detections (Detections): PixelFlow detections object containing bounding boxes.
|
|
31
31
|
Each detection must have a `.bbox` attribute with
|
|
32
32
|
(x1, y1, x2, y2) coordinates.
|
|
@@ -38,8 +38,8 @@ def oval(
|
|
|
38
38
|
end_angle (int): Ending angle of the ellipse arc in degrees.
|
|
39
39
|
Range: -180 to 360. Default is 235 (bottom-right, creating
|
|
40
40
|
bottom arc spanning ~280 degrees).
|
|
41
|
-
colors (Optional[List[Tuple[int, int, int]]]): List of
|
|
42
|
-
(
|
|
41
|
+
colors (Optional[List[Tuple[int, int, int]]]): List of RGB color tuples
|
|
42
|
+
(R, G, B) where each value is
|
|
43
43
|
0-255. Colors are mapped to unique
|
|
44
44
|
class_ids in order of appearance.
|
|
45
45
|
If None, uses default ColorManager colors.
|
|
@@ -23,15 +23,15 @@ def polygon(
|
|
|
23
23
|
color schemes for visual distinction between different object classes.
|
|
24
24
|
|
|
25
25
|
Args:
|
|
26
|
-
image (np.ndarray): Input image to draw polygons on. Must be a valid
|
|
26
|
+
image (np.ndarray): Input image to draw polygons on. Must be a valid RGB image array.
|
|
27
27
|
detections (Detections): Detections object containing segmentation data.
|
|
28
28
|
Each detection must have a 'segments' attribute with polygon coordinates.
|
|
29
29
|
thickness (Optional[int]): Line thickness for polygon outlines in pixels.
|
|
30
30
|
If None, automatically calculated based on image dimensions.
|
|
31
31
|
Range: [1-50]. Default is adaptive (typically 1-6).
|
|
32
|
-
colors (Optional[List[Tuple[int, int, int]]]): List of
|
|
32
|
+
colors (Optional[List[Tuple[int, int, int]]]): List of RGB color tuples to override default colors.
|
|
33
33
|
Colors are cycled through unique class_ids in order of appearance.
|
|
34
|
-
Each tuple should be (
|
|
34
|
+
Each tuple should be (R, G, B) with values [0-255].
|
|
35
35
|
If None, uses default ColorManager colors.
|
|
36
36
|
|
|
37
37
|
Returns:
|
|
@@ -57,7 +57,7 @@ def polygon(
|
|
|
57
57
|
>>> annotated = pf.annotators.polygon(image, results)
|
|
58
58
|
>>>
|
|
59
59
|
>>> # Customize line thickness and colors
|
|
60
|
-
>>> custom_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] #
|
|
60
|
+
>>> custom_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] # Red, Green, Blue
|
|
61
61
|
>>> annotated = pf.annotators.polygon(image, results, thickness=3, colors=custom_colors)
|
|
62
62
|
>>>
|
|
63
63
|
>>> # Use adaptive thickness on high-resolution image
|
|
@@ -32,16 +32,16 @@ def _get_adaptive_params(image):
|
|
|
32
32
|
base_scale = np.sqrt(width * height) / 1000 * ADAPTIVE_SCALE_MULTIPLIER
|
|
33
33
|
|
|
34
34
|
params = {
|
|
35
|
-
'thickness': max(1, int(base_scale *
|
|
36
|
-
'font_scale': max(0.3, base_scale * 0.
|
|
37
|
-
'font_thickness': max(1, int(base_scale *
|
|
38
|
-
'padding': max(2, int(base_scale *
|
|
39
|
-
'margin': max(1, int(base_scale *
|
|
40
|
-
'text_offset': max(10, int(base_scale *
|
|
41
|
-
'blur_kernel': max(3, int(base_scale *
|
|
35
|
+
'thickness': max(1, int(base_scale * 3)),
|
|
36
|
+
'font_scale': max(0.3, base_scale * 0.6),
|
|
37
|
+
'font_thickness': max(1, int(base_scale * 2.5)),
|
|
38
|
+
'padding': max(2, int(base_scale * 8)),
|
|
39
|
+
'margin': max(1, int(base_scale * 3)),
|
|
40
|
+
'text_offset': max(10, int(base_scale * 25)),
|
|
41
|
+
'blur_kernel': max(3, int(base_scale * 25)) | 1, # ensure odd number
|
|
42
42
|
'pixel_size': max(2, int(base_scale * 10)),
|
|
43
|
-
'corner_radius': max(0, int(base_scale *
|
|
44
|
-
'shadow_offset': max(1, int(base_scale *
|
|
43
|
+
'corner_radius': max(0, int(base_scale * 8)),
|
|
44
|
+
'shadow_offset': max(1, int(base_scale * 3)),
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
_adaptive_cache[shape_key] = params
|
|
@@ -28,7 +28,7 @@ def zones(
|
|
|
28
28
|
thickness based on image resolution for optimal visibility across different image sizes.
|
|
29
29
|
|
|
30
30
|
Args:
|
|
31
|
-
image (np.ndarray): Input image to annotate. Must be 3-channel
|
|
31
|
+
image (np.ndarray): Input image to annotate. Must be 3-channel RGB format.
|
|
32
32
|
zone_manager: ZoneManager instance containing polygon zones with associated metadata.
|
|
33
33
|
Must have 'zones' attribute containing Zone objects with polygon, color,
|
|
34
34
|
name, and count attributes.
|