mas-ods 0.2.4__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.
- mas_ods-0.2.4/PKG-INFO +138 -0
- mas_ods-0.2.4/README.md +119 -0
- mas_ods-0.2.4/pyproject.toml +36 -0
- mas_ods-0.2.4/pyproject.toml.orig +32 -0
- mas_ods-0.2.4/src/mas_ods/__init__.py +82 -0
- mas_ods-0.2.4/src/mas_ods/benchmark/__init__.py +3 -0
- mas_ods-0.2.4/src/mas_ods/benchmark/profiler.py +106 -0
- mas_ods-0.2.4/src/mas_ods/cli/__init__.py +3 -0
- mas_ods-0.2.4/src/mas_ods/cli/main.py +372 -0
- mas_ods-0.2.4/src/mas_ods/core/__init__.py +4 -0
- mas_ods-0.2.4/src/mas_ods/core/config.py +25 -0
- mas_ods-0.2.4/src/mas_ods/core/structures.py +314 -0
- mas_ods-0.2.4/src/mas_ods/engine/__init__.py +17 -0
- mas_ods-0.2.4/src/mas_ods/engine/hardware.py +90 -0
- mas_ods-0.2.4/src/mas_ods/engine/session.py +141 -0
- mas_ods-0.2.4/src/mas_ods/models/__init__.py +15 -0
- mas_ods-0.2.4/src/mas_ods/models/hub.py +354 -0
- mas_ods-0.2.4/src/mas_ods/pipeline/__init__.py +4 -0
- mas_ods-0.2.4/src/mas_ods/pipeline/detector.py +159 -0
- mas_ods-0.2.4/src/mas_ods/pipeline/hand.py +226 -0
- mas_ods-0.2.4/src/mas_ods/pipeline/palm.py +199 -0
- mas_ods-0.2.4/src/mas_ods/pipeline/pose.py +459 -0
- mas_ods-0.2.4/src/mas_ods/pipeline/stream.py +72 -0
- mas_ods-0.2.4/src/mas_ods/pipeline/vehicle.py +150 -0
- mas_ods-0.2.4/src/mas_ods/processing/__init__.py +5 -0
- mas_ods-0.2.4/src/mas_ods/processing/postprocessor.py +448 -0
- mas_ods-0.2.4/src/mas_ods/processing/preprocessor.py +139 -0
- mas_ods-0.2.4/src/mas_ods/processing/visualizer.py +185 -0
- mas_ods-0.2.4/src/mas_ods/tracking/counter.py +126 -0
- mas_ods-0.2.4/src/mas_ods/tracking/tracker.py +209 -0
mas_ods-0.2.4/PKG-INFO
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: mas-ods
|
|
3
|
+
Version: 0.2.4
|
|
4
|
+
Summary: Ultra-lightweight, high-accuracy single-class person detection library
|
|
5
|
+
Author: MASWorld, Prasad Maskar
|
|
6
|
+
Author-email: MASWorld <masworldit@gmail.com>, Prasad Maskar <prasad.maskar7@gmail.com>
|
|
7
|
+
Requires-Dist: numpy>=2.0.0
|
|
8
|
+
Requires-Dist: nvidia-cudnn-cu12>=9.24.0.43
|
|
9
|
+
Requires-Dist: onnx>=1.16.0
|
|
10
|
+
Requires-Dist: onnxruntime>=1.18.0
|
|
11
|
+
Requires-Dist: onnxruntime-gpu>=1.18.0
|
|
12
|
+
Requires-Dist: opencv-python>=4.8.0
|
|
13
|
+
Requires-Dist: pillow>=10.0.0
|
|
14
|
+
Requires-Dist: nvidia-cudnn-cu12>=9.0.0 ; extra == 'gpu'
|
|
15
|
+
Requires-Dist: nvidia-cublas-cu12>=12.0.0 ; extra == 'gpu'
|
|
16
|
+
Requires-Python: >=3.13
|
|
17
|
+
Provides-Extra: gpu
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# mas-ods 🚀
|
|
21
|
+
|
|
22
|
+
**mas-ods** is an ultra-lightweight, high-accuracy, single-class (`person`) object detection engine and model hub designed for extreme cost efficiency and high throughput on CPUs, edge devices, and GPUs.
|
|
23
|
+
|
|
24
|
+
Built from the ground up for production deployment, **mas-ods** runs exclusively on **ONNX Runtime** with pure NumPy/OpenCV pre/post-processing, automatic model downloading from Google Drive into a local `.models/` directory, seamless CPU/GPU/AUTO hardware toggles, and 100% **Apache-2.0** commercial compliance.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 🌟 Key Features
|
|
29
|
+
|
|
30
|
+
* **⚡ Ultra-Lightweight & Fast:** Sub-5ms latency and 150–250+ FPS on standard CPUs.
|
|
31
|
+
* **🌐 Dynamic Model Hub (Auto-Download):** Simply pass the model name (e.g. `PersonDetector("yolox_nano")`) and the model is automatically downloaded into `.models/` on first run.
|
|
32
|
+
* **🎯 Single-Class Person Focus:** Eliminates multi-class softmax/NMS overhead for maximum efficiency.
|
|
33
|
+
* **💻 Pure ONNX Runtime Core:** No heavy PyTorch or PaddlePaddle dependencies needed during inference.
|
|
34
|
+
* **🔄 AUTO Hardware Acceleration:** Choose between `device="auto"`, `"cpu"`, `"gpu"`, `"cuda"`, or `"directml"` with automatic graceful fallback.
|
|
35
|
+
* **📊 Profiling & Diagnostics:** Built-in latency (P50/P95/P99), FPS, and hardware execution provider benchmark suite.
|
|
36
|
+
* **⚖️ Commercial Friendly:** Free from copyleft/AGPL constraints (Apache-2.0).
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 📦 Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Using uv (recommended)
|
|
44
|
+
uv add mas-ods
|
|
45
|
+
|
|
46
|
+
# Or using pip
|
|
47
|
+
pip install mas-ods
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 🚀 Quickstart
|
|
53
|
+
|
|
54
|
+
### 1. Python API (Zero Setup — Auto Downloads Model)
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import cv2
|
|
58
|
+
from mas_ods import PersonDetector
|
|
59
|
+
|
|
60
|
+
# 1. Initialize detector by model name (automatically downloads if not cached)
|
|
61
|
+
# Models available: "yolox_nano", "nanodet-plus-m_320", "nanodet-plus-m_416", "yolox_tiny", "yolox_s", "yolox_m"
|
|
62
|
+
detector = PersonDetector(
|
|
63
|
+
model="yolox_nano", # or pass custom local file path: "path/to/model.onnx"
|
|
64
|
+
device="auto", # "auto" (prioritizes GPU with CPU fallback) | "cpu" | "gpu"
|
|
65
|
+
confidence_threshold=0.40, # Filter out low-confidence predictions
|
|
66
|
+
iou_threshold=0.45, # NMS IoU threshold
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# 2. Run inference on an image (filepath, numpy array, or PIL image)
|
|
70
|
+
image = cv2.imread("street.jpg")
|
|
71
|
+
result = detector.predict(image)
|
|
72
|
+
|
|
73
|
+
print(f"Persons detected: {result.count}")
|
|
74
|
+
print(f"Total time: {result.total_time_ms:.2f} ms ({result.fps:.1f} FPS)")
|
|
75
|
+
|
|
76
|
+
for box in result.boxes:
|
|
77
|
+
print(f"Coordinates: {box.xyxy} | Confidence: {box.score:.2f}")
|
|
78
|
+
|
|
79
|
+
# 3. Render bounding boxes and HUD overlay
|
|
80
|
+
annotated_frame = detector.render(image, result, show_fps=True)
|
|
81
|
+
cv2.imwrite("output.jpg", annotated_frame)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 2. Real-Time Webcam / Video Stream
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from mas_ods import PersonDetector, VideoPipeline
|
|
88
|
+
|
|
89
|
+
detector = PersonDetector(model="yolox_nano", device="auto")
|
|
90
|
+
pipeline = VideoPipeline(detector)
|
|
91
|
+
|
|
92
|
+
# Stream from webcam (0) or video file ("video.mp4")
|
|
93
|
+
pipeline.process_stream(source=0, show=True)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 📋 Available Model Catalog
|
|
99
|
+
|
|
100
|
+
| Model Name | Input Shape | Model Size | Description |
|
|
101
|
+
| :--- | :--- | :--- | :--- |
|
|
102
|
+
| **`yolox_nano`** | 416x416 | **~3.7 MB** | Ultra-lightweight (0.91M params), 150–250+ FPS on CPU |
|
|
103
|
+
| **`nanodet-plus-m_320`** | 320x320 | **~4.8 MB** | Ultra-fast anchor-free CPU detector |
|
|
104
|
+
| **`nanodet-plus-m_416`** | 416x416 | **~4.8 MB** | High resolution anchor-free CPU detector |
|
|
105
|
+
| **`nanodet-plus-m-1.5x_416`** | 416x416 | **~9.9 MB** | High accuracy anchor-free detector |
|
|
106
|
+
| **`yolox_tiny`** | 416x416 | **~20.2 MB**| Balanced speed and accuracy (~5M params) |
|
|
107
|
+
| **`yolox_s`** | 640x640 | **~35.9 MB**| Small detector (~9M params), great for GPU |
|
|
108
|
+
| **`yolox_m`** | 640x640 | **~101.3 MB**| Medium detector (~25M params) |
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 🖥️ Command-Line Interface (CLI)
|
|
113
|
+
|
|
114
|
+
### List Available Models in the Catalog
|
|
115
|
+
```bash
|
|
116
|
+
mas-ods models
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Check Hardware & Available Execution Providers
|
|
120
|
+
```bash
|
|
121
|
+
mas-ods devices
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Benchmark Latency & Throughput (FPS)
|
|
125
|
+
```bash
|
|
126
|
+
mas-ods benchmark --model yolox_nano --device auto --iterations 100
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Run Detection via CLI
|
|
130
|
+
```bash
|
|
131
|
+
mas-ods detect --model yolox_nano --source test.jpg --device auto --save output.jpg
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 📄 License
|
|
137
|
+
|
|
138
|
+
This project is licensed under the [Apache License 2.0](LICENSE) - free for both commercial and personal use.
|
mas_ods-0.2.4/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# mas-ods 🚀
|
|
2
|
+
|
|
3
|
+
**mas-ods** is an ultra-lightweight, high-accuracy, single-class (`person`) object detection engine and model hub designed for extreme cost efficiency and high throughput on CPUs, edge devices, and GPUs.
|
|
4
|
+
|
|
5
|
+
Built from the ground up for production deployment, **mas-ods** runs exclusively on **ONNX Runtime** with pure NumPy/OpenCV pre/post-processing, automatic model downloading from Google Drive into a local `.models/` directory, seamless CPU/GPU/AUTO hardware toggles, and 100% **Apache-2.0** commercial compliance.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🌟 Key Features
|
|
10
|
+
|
|
11
|
+
* **⚡ Ultra-Lightweight & Fast:** Sub-5ms latency and 150–250+ FPS on standard CPUs.
|
|
12
|
+
* **🌐 Dynamic Model Hub (Auto-Download):** Simply pass the model name (e.g. `PersonDetector("yolox_nano")`) and the model is automatically downloaded into `.models/` on first run.
|
|
13
|
+
* **🎯 Single-Class Person Focus:** Eliminates multi-class softmax/NMS overhead for maximum efficiency.
|
|
14
|
+
* **💻 Pure ONNX Runtime Core:** No heavy PyTorch or PaddlePaddle dependencies needed during inference.
|
|
15
|
+
* **🔄 AUTO Hardware Acceleration:** Choose between `device="auto"`, `"cpu"`, `"gpu"`, `"cuda"`, or `"directml"` with automatic graceful fallback.
|
|
16
|
+
* **📊 Profiling & Diagnostics:** Built-in latency (P50/P95/P99), FPS, and hardware execution provider benchmark suite.
|
|
17
|
+
* **⚖️ Commercial Friendly:** Free from copyleft/AGPL constraints (Apache-2.0).
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 📦 Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Using uv (recommended)
|
|
25
|
+
uv add mas-ods
|
|
26
|
+
|
|
27
|
+
# Or using pip
|
|
28
|
+
pip install mas-ods
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 🚀 Quickstart
|
|
34
|
+
|
|
35
|
+
### 1. Python API (Zero Setup — Auto Downloads Model)
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import cv2
|
|
39
|
+
from mas_ods import PersonDetector
|
|
40
|
+
|
|
41
|
+
# 1. Initialize detector by model name (automatically downloads if not cached)
|
|
42
|
+
# Models available: "yolox_nano", "nanodet-plus-m_320", "nanodet-plus-m_416", "yolox_tiny", "yolox_s", "yolox_m"
|
|
43
|
+
detector = PersonDetector(
|
|
44
|
+
model="yolox_nano", # or pass custom local file path: "path/to/model.onnx"
|
|
45
|
+
device="auto", # "auto" (prioritizes GPU with CPU fallback) | "cpu" | "gpu"
|
|
46
|
+
confidence_threshold=0.40, # Filter out low-confidence predictions
|
|
47
|
+
iou_threshold=0.45, # NMS IoU threshold
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# 2. Run inference on an image (filepath, numpy array, or PIL image)
|
|
51
|
+
image = cv2.imread("street.jpg")
|
|
52
|
+
result = detector.predict(image)
|
|
53
|
+
|
|
54
|
+
print(f"Persons detected: {result.count}")
|
|
55
|
+
print(f"Total time: {result.total_time_ms:.2f} ms ({result.fps:.1f} FPS)")
|
|
56
|
+
|
|
57
|
+
for box in result.boxes:
|
|
58
|
+
print(f"Coordinates: {box.xyxy} | Confidence: {box.score:.2f}")
|
|
59
|
+
|
|
60
|
+
# 3. Render bounding boxes and HUD overlay
|
|
61
|
+
annotated_frame = detector.render(image, result, show_fps=True)
|
|
62
|
+
cv2.imwrite("output.jpg", annotated_frame)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 2. Real-Time Webcam / Video Stream
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from mas_ods import PersonDetector, VideoPipeline
|
|
69
|
+
|
|
70
|
+
detector = PersonDetector(model="yolox_nano", device="auto")
|
|
71
|
+
pipeline = VideoPipeline(detector)
|
|
72
|
+
|
|
73
|
+
# Stream from webcam (0) or video file ("video.mp4")
|
|
74
|
+
pipeline.process_stream(source=0, show=True)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 📋 Available Model Catalog
|
|
80
|
+
|
|
81
|
+
| Model Name | Input Shape | Model Size | Description |
|
|
82
|
+
| :--- | :--- | :--- | :--- |
|
|
83
|
+
| **`yolox_nano`** | 416x416 | **~3.7 MB** | Ultra-lightweight (0.91M params), 150–250+ FPS on CPU |
|
|
84
|
+
| **`nanodet-plus-m_320`** | 320x320 | **~4.8 MB** | Ultra-fast anchor-free CPU detector |
|
|
85
|
+
| **`nanodet-plus-m_416`** | 416x416 | **~4.8 MB** | High resolution anchor-free CPU detector |
|
|
86
|
+
| **`nanodet-plus-m-1.5x_416`** | 416x416 | **~9.9 MB** | High accuracy anchor-free detector |
|
|
87
|
+
| **`yolox_tiny`** | 416x416 | **~20.2 MB**| Balanced speed and accuracy (~5M params) |
|
|
88
|
+
| **`yolox_s`** | 640x640 | **~35.9 MB**| Small detector (~9M params), great for GPU |
|
|
89
|
+
| **`yolox_m`** | 640x640 | **~101.3 MB**| Medium detector (~25M params) |
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 🖥️ Command-Line Interface (CLI)
|
|
94
|
+
|
|
95
|
+
### List Available Models in the Catalog
|
|
96
|
+
```bash
|
|
97
|
+
mas-ods models
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Check Hardware & Available Execution Providers
|
|
101
|
+
```bash
|
|
102
|
+
mas-ods devices
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Benchmark Latency & Throughput (FPS)
|
|
106
|
+
```bash
|
|
107
|
+
mas-ods benchmark --model yolox_nano --device auto --iterations 100
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Run Detection via CLI
|
|
111
|
+
```bash
|
|
112
|
+
mas-ods detect --model yolox_nano --source test.jpg --device auto --save output.jpg
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 📄 License
|
|
118
|
+
|
|
119
|
+
This project is licensed under the [Apache License 2.0](LICENSE) - free for both commercial and personal use.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "mas-ods"
|
|
3
|
+
version = "0.2.4"
|
|
4
|
+
description = "Ultra-lightweight, high-accuracy single-class person detection library"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"numpy>=2.0.0",
|
|
9
|
+
"nvidia-cudnn-cu12>=9.24.0.43",
|
|
10
|
+
"onnx>=1.16.0",
|
|
11
|
+
"onnxruntime>=1.18.0",
|
|
12
|
+
"onnxruntime-gpu>=1.18.0",
|
|
13
|
+
"opencv-python>=4.8.0",
|
|
14
|
+
"pillow>=10.0.0",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[[project.authors]]
|
|
18
|
+
name = "MASWorld"
|
|
19
|
+
email = "masworldit@gmail.com"
|
|
20
|
+
|
|
21
|
+
[[project.authors]]
|
|
22
|
+
name = "Prasad Maskar"
|
|
23
|
+
email = "prasad.maskar7@gmail.com"
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
gpu = [
|
|
27
|
+
"nvidia-cudnn-cu12>=9.0.0",
|
|
28
|
+
"nvidia-cublas-cu12>=12.0.0",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.scripts]
|
|
32
|
+
mas-ods = "mas_ods.cli.main:main"
|
|
33
|
+
|
|
34
|
+
[build-system]
|
|
35
|
+
requires = ["uv_build>=0.12.5,<0.13.0"]
|
|
36
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "mas-ods"
|
|
3
|
+
version = "0.2.4"
|
|
4
|
+
description = "Ultra-lightweight, high-accuracy single-class person detection library"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "MASWorld", email = "masworldit@gmail.com" },
|
|
8
|
+
{ name = "Prasad Maskar", email="prasad.maskar7@gmail.com"}
|
|
9
|
+
]
|
|
10
|
+
requires-python = ">=3.13"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"numpy>=2.0.0",
|
|
13
|
+
"nvidia-cudnn-cu12>=9.24.0.43",
|
|
14
|
+
"onnx>=1.16.0",
|
|
15
|
+
"onnxruntime>=1.18.0",
|
|
16
|
+
"onnxruntime-gpu>=1.18.0",
|
|
17
|
+
"opencv-python>=4.8.0",
|
|
18
|
+
"pillow>=10.0.0",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project.optional-dependencies]
|
|
22
|
+
gpu = [
|
|
23
|
+
"nvidia-cudnn-cu12>=9.0.0",
|
|
24
|
+
"nvidia-cublas-cu12>=12.0.0",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.scripts]
|
|
28
|
+
mas-ods = "mas_ods.cli.main:main"
|
|
29
|
+
|
|
30
|
+
[build-system]
|
|
31
|
+
requires = ["uv_build>=0.12.5,<0.13.0"]
|
|
32
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""
|
|
2
|
+
mas-ods: Ultra-lightweight, high-accuracy single-class person detection engine & model hub.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
__version__ = "0.2.4"
|
|
6
|
+
__author__ = "MASWorld"
|
|
7
|
+
|
|
8
|
+
from mas_ods.core.structures import (
|
|
9
|
+
BoundingBox,
|
|
10
|
+
DetectionResult,
|
|
11
|
+
DeviceType,
|
|
12
|
+
Keypoint,
|
|
13
|
+
PoseResult,
|
|
14
|
+
MultiPoseResult,
|
|
15
|
+
HandResult,
|
|
16
|
+
TrackedObject,
|
|
17
|
+
COCO_KEYPOINTS,
|
|
18
|
+
COCO_SKELETON_EDGES,
|
|
19
|
+
HAND_LANDMARK_EDGES,
|
|
20
|
+
)
|
|
21
|
+
from mas_ods.core.config import DetectorConfig
|
|
22
|
+
from mas_ods.pipeline.detector import PersonDetector
|
|
23
|
+
from mas_ods.pipeline.vehicle import VehicleDetector, COCO_VEHICLE_CLASSES
|
|
24
|
+
from mas_ods.pipeline.pose import PoseDetector
|
|
25
|
+
from mas_ods.pipeline.hand import HandDetector, HandTracker
|
|
26
|
+
from mas_ods.pipeline.palm import PalmDetector
|
|
27
|
+
from mas_ods.pipeline.stream import VideoPipeline
|
|
28
|
+
from mas_ods.tracking.tracker import ByteTracker
|
|
29
|
+
from mas_ods.tracking.counter import LineCrossingCounter
|
|
30
|
+
from mas_ods.processing.visualizer import Visualizer
|
|
31
|
+
from mas_ods.benchmark.profiler import BenchmarkProfiler
|
|
32
|
+
from mas_ods.models.hub import (
|
|
33
|
+
MODEL_REGISTRY,
|
|
34
|
+
resolve_model,
|
|
35
|
+
list_models,
|
|
36
|
+
get_model_info,
|
|
37
|
+
)
|
|
38
|
+
from mas_ods.engine.hardware import (
|
|
39
|
+
get_available_providers,
|
|
40
|
+
is_gpu_available,
|
|
41
|
+
is_cuda_available,
|
|
42
|
+
is_directml_available,
|
|
43
|
+
get_hardware_info,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
__all__ = [
|
|
47
|
+
"__version__",
|
|
48
|
+
"__author__",
|
|
49
|
+
"BoundingBox",
|
|
50
|
+
"DetectionResult",
|
|
51
|
+
"DeviceType",
|
|
52
|
+
"DetectorConfig",
|
|
53
|
+
"Keypoint",
|
|
54
|
+
"PoseResult",
|
|
55
|
+
"MultiPoseResult",
|
|
56
|
+
"HandResult",
|
|
57
|
+
"TrackedObject",
|
|
58
|
+
"COCO_KEYPOINTS",
|
|
59
|
+
"COCO_SKELETON_EDGES",
|
|
60
|
+
"HAND_LANDMARK_EDGES",
|
|
61
|
+
"COCO_VEHICLE_CLASSES",
|
|
62
|
+
"PersonDetector",
|
|
63
|
+
"VehicleDetector",
|
|
64
|
+
"PalmDetector",
|
|
65
|
+
"HandDetector",
|
|
66
|
+
"HandTracker",
|
|
67
|
+
"PoseDetector",
|
|
68
|
+
"ByteTracker",
|
|
69
|
+
"LineCrossingCounter",
|
|
70
|
+
"Visualizer",
|
|
71
|
+
"VideoPipeline",
|
|
72
|
+
"BenchmarkProfiler",
|
|
73
|
+
"MODEL_REGISTRY",
|
|
74
|
+
"resolve_model",
|
|
75
|
+
"list_models",
|
|
76
|
+
"get_model_info",
|
|
77
|
+
"get_available_providers",
|
|
78
|
+
"is_gpu_available",
|
|
79
|
+
"is_cuda_available",
|
|
80
|
+
"is_directml_available",
|
|
81
|
+
"get_hardware_info",
|
|
82
|
+
]
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Dict, Any, Tuple
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
from mas_ods.pipeline.detector import PersonDetector
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BenchmarkProfiler:
|
|
13
|
+
"""
|
|
14
|
+
Measures latency percentiles, throughput (FPS), and execution breakdown
|
|
15
|
+
for ONNX models across CPU and GPU backends.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, detector: PersonDetector):
|
|
19
|
+
self.detector = detector
|
|
20
|
+
|
|
21
|
+
def run(
|
|
22
|
+
self,
|
|
23
|
+
iterations: int = 100,
|
|
24
|
+
warmup_iterations: int = 10,
|
|
25
|
+
image_shape: Tuple[int, int] = (640, 640),
|
|
26
|
+
) -> Dict[str, Any]:
|
|
27
|
+
"""
|
|
28
|
+
Executes benchmark with synthetic image frames.
|
|
29
|
+
"""
|
|
30
|
+
h, w = image_shape
|
|
31
|
+
dummy_frame = (np.random.rand(h, w, 3) * 255).astype(np.uint8)
|
|
32
|
+
|
|
33
|
+
# Warmup
|
|
34
|
+
for _ in range(warmup_iterations):
|
|
35
|
+
_ = self.detector.predict(dummy_frame)
|
|
36
|
+
|
|
37
|
+
# Timed runs
|
|
38
|
+
total_latencies = []
|
|
39
|
+
preprocess_latencies = []
|
|
40
|
+
inference_latencies = []
|
|
41
|
+
postprocess_latencies = []
|
|
42
|
+
|
|
43
|
+
for _ in range(iterations):
|
|
44
|
+
res = self.detector.predict(dummy_frame)
|
|
45
|
+
total_latencies.append(res.total_time_ms)
|
|
46
|
+
preprocess_latencies.append(res.preprocess_time_ms)
|
|
47
|
+
inference_latencies.append(res.inference_time_ms)
|
|
48
|
+
postprocess_latencies.append(res.postprocess_time_ms)
|
|
49
|
+
|
|
50
|
+
total_latencies = np.array(total_latencies)
|
|
51
|
+
inference_latencies = np.array(inference_latencies)
|
|
52
|
+
|
|
53
|
+
mean_total = float(np.mean(total_latencies))
|
|
54
|
+
p50 = float(np.percentile(total_latencies, 50))
|
|
55
|
+
p95 = float(np.percentile(total_latencies, 95))
|
|
56
|
+
p99 = float(np.percentile(total_latencies, 99))
|
|
57
|
+
min_lat = float(np.min(total_latencies))
|
|
58
|
+
max_lat = float(np.max(total_latencies))
|
|
59
|
+
fps = 1000.0 / mean_total if mean_total > 0 else 0.0
|
|
60
|
+
|
|
61
|
+
mean_infer = float(np.mean(inference_latencies))
|
|
62
|
+
mean_pre = float(np.mean(preprocess_latencies))
|
|
63
|
+
mean_post = float(np.mean(postprocess_latencies))
|
|
64
|
+
|
|
65
|
+
report = {
|
|
66
|
+
"model_name": self.detector.model_name,
|
|
67
|
+
"active_provider": self.detector.active_provider,
|
|
68
|
+
"iterations": iterations,
|
|
69
|
+
"mean_latency_ms": round(mean_total, 2),
|
|
70
|
+
"inference_latency_ms": round(mean_infer, 2),
|
|
71
|
+
"preprocess_latency_ms": round(mean_pre, 2),
|
|
72
|
+
"postprocess_latency_ms": round(mean_post, 2),
|
|
73
|
+
"p50_ms": round(p50, 2),
|
|
74
|
+
"p95_ms": round(p95, 2),
|
|
75
|
+
"p99_ms": round(p99, 2),
|
|
76
|
+
"min_ms": round(min_lat, 2),
|
|
77
|
+
"max_ms": round(max_lat, 2),
|
|
78
|
+
"fps": round(fps, 1),
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return report
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def format_table(report: Dict[str, Any]) -> str:
|
|
85
|
+
"""Formats report as a clean ASCII table."""
|
|
86
|
+
lines = [
|
|
87
|
+
"=" * 55,
|
|
88
|
+
" MAS-ODS PERFORMANCE BENCHMARK REPORT",
|
|
89
|
+
"=" * 55,
|
|
90
|
+
f" Model: {report['model_name']}",
|
|
91
|
+
f" Provider: {report['active_provider']}",
|
|
92
|
+
f" Iterations: {report['iterations']}",
|
|
93
|
+
"-" * 55,
|
|
94
|
+
f" Throughput (FPS): {report['fps']:.1f} FPS",
|
|
95
|
+
f" Mean Total: {report['mean_latency_ms']:.2f} ms",
|
|
96
|
+
f" Pure Inference: {report['inference_latency_ms']:.2f} ms",
|
|
97
|
+
f" Pre-processing: {report['preprocess_latency_ms']:.2f} ms",
|
|
98
|
+
f" Post-processing: {report['postprocess_latency_ms']:.2f} ms",
|
|
99
|
+
"-" * 55,
|
|
100
|
+
f" Latency P50: {report['p50_ms']:.2f} ms",
|
|
101
|
+
f" Latency P95: {report['p95_ms']:.2f} ms",
|
|
102
|
+
f" Latency P99: {report['p99_ms']:.2f} ms",
|
|
103
|
+
f" Latency Min/Max: {report['min_ms']:.2f} ms / {report['max_ms']:.2f} ms",
|
|
104
|
+
"=" * 55,
|
|
105
|
+
]
|
|
106
|
+
return "\n".join(lines)
|