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.
Files changed (30) hide show
  1. mas_ods-0.2.4/PKG-INFO +138 -0
  2. mas_ods-0.2.4/README.md +119 -0
  3. mas_ods-0.2.4/pyproject.toml +36 -0
  4. mas_ods-0.2.4/pyproject.toml.orig +32 -0
  5. mas_ods-0.2.4/src/mas_ods/__init__.py +82 -0
  6. mas_ods-0.2.4/src/mas_ods/benchmark/__init__.py +3 -0
  7. mas_ods-0.2.4/src/mas_ods/benchmark/profiler.py +106 -0
  8. mas_ods-0.2.4/src/mas_ods/cli/__init__.py +3 -0
  9. mas_ods-0.2.4/src/mas_ods/cli/main.py +372 -0
  10. mas_ods-0.2.4/src/mas_ods/core/__init__.py +4 -0
  11. mas_ods-0.2.4/src/mas_ods/core/config.py +25 -0
  12. mas_ods-0.2.4/src/mas_ods/core/structures.py +314 -0
  13. mas_ods-0.2.4/src/mas_ods/engine/__init__.py +17 -0
  14. mas_ods-0.2.4/src/mas_ods/engine/hardware.py +90 -0
  15. mas_ods-0.2.4/src/mas_ods/engine/session.py +141 -0
  16. mas_ods-0.2.4/src/mas_ods/models/__init__.py +15 -0
  17. mas_ods-0.2.4/src/mas_ods/models/hub.py +354 -0
  18. mas_ods-0.2.4/src/mas_ods/pipeline/__init__.py +4 -0
  19. mas_ods-0.2.4/src/mas_ods/pipeline/detector.py +159 -0
  20. mas_ods-0.2.4/src/mas_ods/pipeline/hand.py +226 -0
  21. mas_ods-0.2.4/src/mas_ods/pipeline/palm.py +199 -0
  22. mas_ods-0.2.4/src/mas_ods/pipeline/pose.py +459 -0
  23. mas_ods-0.2.4/src/mas_ods/pipeline/stream.py +72 -0
  24. mas_ods-0.2.4/src/mas_ods/pipeline/vehicle.py +150 -0
  25. mas_ods-0.2.4/src/mas_ods/processing/__init__.py +5 -0
  26. mas_ods-0.2.4/src/mas_ods/processing/postprocessor.py +448 -0
  27. mas_ods-0.2.4/src/mas_ods/processing/preprocessor.py +139 -0
  28. mas_ods-0.2.4/src/mas_ods/processing/visualizer.py +185 -0
  29. mas_ods-0.2.4/src/mas_ods/tracking/counter.py +126 -0
  30. 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.
@@ -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,3 @@
1
+ from mas_ods.benchmark.profiler import BenchmarkProfiler
2
+
3
+ __all__ = ["BenchmarkProfiler"]
@@ -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)
@@ -0,0 +1,3 @@
1
+ from mas_ods.cli.main import main
2
+
3
+ __all__ = ["main"]