flashdetect-cu124 1.0.0__py3-none-win_amd64.whl
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.
flashdetect/__init__.py
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FlashDetect Python Wrapper — safe, Pythonic API on top of flashdetect.dll
|
|
3
|
+
"""
|
|
4
|
+
import ctypes
|
|
5
|
+
import os
|
|
6
|
+
import glob
|
|
7
|
+
from typing import List, Optional, Tuple
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
import tensorrt_libs
|
|
11
|
+
os.add_dll_directory(tensorrt_libs.__path__[0])
|
|
12
|
+
except ImportError:
|
|
13
|
+
pass
|
|
14
|
+
_nvidia_base = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'nvidia')
|
|
15
|
+
if os.path.isdir(_nvidia_base):
|
|
16
|
+
for _root, _dirs, _files in os.walk(_nvidia_base):
|
|
17
|
+
if any(f.endswith('.dll') for f in _files):
|
|
18
|
+
os.add_dll_directory(_root)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Detection:
|
|
22
|
+
"""Single detection result."""
|
|
23
|
+
__slots__ = ("x1", "y1", "x2", "y2", "conf", "class_id")
|
|
24
|
+
|
|
25
|
+
def __init__(self, x1: float, y1: float, x2: float, y2: float,
|
|
26
|
+
conf: float, class_id: int):
|
|
27
|
+
self.x1 = x1
|
|
28
|
+
self.y1 = y1
|
|
29
|
+
self.x2 = x2
|
|
30
|
+
self.y2 = y2
|
|
31
|
+
self.conf = conf
|
|
32
|
+
self.class_id = class_id
|
|
33
|
+
|
|
34
|
+
def __repr__(self):
|
|
35
|
+
return (f"Detection(x1={self.x1:.0f}, y1={self.y1:.0f}, "
|
|
36
|
+
f"x2={self.x2:.0f}, y2={self.y2:.0f}, "
|
|
37
|
+
f"cls={self.class_id}, conf={self.conf:.2f})")
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def xyxy(self) -> Tuple[float, float, float, float]:
|
|
41
|
+
return (self.x1, self.y1, self.x2, self.y2)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class FlashDetect:
|
|
45
|
+
"""
|
|
46
|
+
Low-latency YOLO26 inference engine.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
engine_path: str,
|
|
52
|
+
conf: float = 0.25,
|
|
53
|
+
device_id: int = 0,
|
|
54
|
+
target_classes: Optional[List[int]] = None,
|
|
55
|
+
max_dets: int = 0,
|
|
56
|
+
format: str = "BGR",
|
|
57
|
+
resize_mode: int = 0, # 0=no resize (default), 1=GPU resize
|
|
58
|
+
src_w: int = 0, # source width (resize_mode=1)
|
|
59
|
+
src_h: int = 0, # source height (resize_mode=1)
|
|
60
|
+
sdk_dir: Optional[str] = None,
|
|
61
|
+
):
|
|
62
|
+
if sdk_dir is None:
|
|
63
|
+
# Auto-detect: look for flashdetect.dll next to this file
|
|
64
|
+
sdk_dir = os.path.dirname(os.path.abspath(__file__))
|
|
65
|
+
# Also try parent directory's runtime folder
|
|
66
|
+
parent_runtime = os.path.join(os.path.dirname(sdk_dir), "runtime")
|
|
67
|
+
if os.path.isdir(parent_runtime):
|
|
68
|
+
os.add_dll_directory(parent_runtime)
|
|
69
|
+
os.add_dll_directory(sdk_dir)
|
|
70
|
+
|
|
71
|
+
# Find DLL
|
|
72
|
+
dll_path = os.path.join(sdk_dir, "flashdetect.dll")
|
|
73
|
+
if not os.path.exists(dll_path):
|
|
74
|
+
raise FileNotFoundError(f"flashdetect.dll not found in {sdk_dir}")
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
self._dll = ctypes.CDLL(dll_path)
|
|
78
|
+
except OSError as e:
|
|
79
|
+
raise RuntimeError(
|
|
80
|
+
f"Cannot load flashdetect.dll — missing runtime DLLs.\n"
|
|
81
|
+
f" {e}\n"
|
|
82
|
+
f" Ensure CUDA 12.4 + TensorRT 11.0 are installed."
|
|
83
|
+
) from e
|
|
84
|
+
self._setup_ctypes()
|
|
85
|
+
|
|
86
|
+
# Resolve engine path (support glob)
|
|
87
|
+
if not os.path.exists(engine_path):
|
|
88
|
+
candidates = glob.glob(engine_path)
|
|
89
|
+
if not candidates:
|
|
90
|
+
candidates = glob.glob(os.path.join(os.path.dirname(sdk_dir), "*.engine"))
|
|
91
|
+
if candidates:
|
|
92
|
+
engine_path = candidates[0]
|
|
93
|
+
else:
|
|
94
|
+
raise FileNotFoundError(f"Engine not found: {engine_path}")
|
|
95
|
+
|
|
96
|
+
# Prepare target classes
|
|
97
|
+
n_labels = len(target_classes) if target_classes else 0
|
|
98
|
+
c_labels = (ctypes.c_int * n_labels)(*target_classes) if target_classes else None
|
|
99
|
+
|
|
100
|
+
# Convert format string to DLL value
|
|
101
|
+
fmt_map = {"BGR": 0, "RGB": 1}
|
|
102
|
+
fmt_val = fmt_map.get(format.upper(), 0)
|
|
103
|
+
|
|
104
|
+
# Create context
|
|
105
|
+
self._ctx = self._dll.fd_create(
|
|
106
|
+
engine_path.encode("utf-8"),
|
|
107
|
+
ctypes.c_float(conf),
|
|
108
|
+
ctypes.c_int(device_id),
|
|
109
|
+
c_labels,
|
|
110
|
+
ctypes.c_int(n_labels),
|
|
111
|
+
ctypes.c_int(max_dets),
|
|
112
|
+
ctypes.c_int(fmt_val),
|
|
113
|
+
ctypes.c_int(resize_mode),
|
|
114
|
+
ctypes.c_int(src_w),
|
|
115
|
+
ctypes.c_int(src_h),
|
|
116
|
+
)
|
|
117
|
+
if not self._ctx:
|
|
118
|
+
# Try to get machine ID to guide the user
|
|
119
|
+
try:
|
|
120
|
+
mid = get_machine_id()
|
|
121
|
+
except Exception:
|
|
122
|
+
mid = "<unavailable>"
|
|
123
|
+
raise RuntimeError(
|
|
124
|
+
f"fd_create failed — likely missing or invalid license.key\n"
|
|
125
|
+
f" Your machine ID: {mid}\n"
|
|
126
|
+
f" Send this ID to the vendor to obtain a license.key file,\n"
|
|
127
|
+
f" then place it beside flashdetect.dll.\n"
|
|
128
|
+
f" Or run: python -c \"import flashdetect; print(flashdetect.get_machine_id())\""
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Get engine input size
|
|
132
|
+
h, w = ctypes.c_int(), ctypes.c_int()
|
|
133
|
+
self._dll.fd_get_size(self._ctx, ctypes.byref(h), ctypes.byref(w))
|
|
134
|
+
self.input_height = h.value
|
|
135
|
+
self.input_width = w.value
|
|
136
|
+
self.resize_mode = resize_mode
|
|
137
|
+
self._src_w = src_w if src_w > 0 else self.input_width
|
|
138
|
+
self._src_h = src_h if src_h > 0 else self.input_height
|
|
139
|
+
|
|
140
|
+
# ── ctypes setup ──────────────────────────────
|
|
141
|
+
|
|
142
|
+
def _setup_ctypes(self):
|
|
143
|
+
d = self._dll
|
|
144
|
+
|
|
145
|
+
class _Ctx(ctypes.Structure):
|
|
146
|
+
pass
|
|
147
|
+
|
|
148
|
+
class _Det(ctypes.Structure):
|
|
149
|
+
_fields_ = [
|
|
150
|
+
("x1", ctypes.c_float), ("y1", ctypes.c_float),
|
|
151
|
+
("x2", ctypes.c_float), ("y2", ctypes.c_float),
|
|
152
|
+
("conf", ctypes.c_float), ("class_id", ctypes.c_int),
|
|
153
|
+
]
|
|
154
|
+
|
|
155
|
+
d.fd_create.argtypes = [
|
|
156
|
+
ctypes.c_char_p, ctypes.c_float, ctypes.c_int,
|
|
157
|
+
ctypes.POINTER(ctypes.c_int), ctypes.c_int, ctypes.c_int, ctypes.c_int,
|
|
158
|
+
ctypes.c_int, ctypes.c_int, ctypes.c_int,
|
|
159
|
+
]
|
|
160
|
+
d.fd_create.restype = ctypes.POINTER(_Ctx)
|
|
161
|
+
|
|
162
|
+
d.fd_process.argtypes = [
|
|
163
|
+
ctypes.POINTER(_Ctx), ctypes.POINTER(ctypes.c_uint8),
|
|
164
|
+
ctypes.POINTER(_Det), ctypes.c_int, ctypes.POINTER(ctypes.c_int),
|
|
165
|
+
]
|
|
166
|
+
d.fd_process.restype = ctypes.c_int
|
|
167
|
+
|
|
168
|
+
d.fd_get_size.argtypes = [
|
|
169
|
+
ctypes.POINTER(_Ctx), ctypes.POINTER(ctypes.c_int),
|
|
170
|
+
ctypes.POINTER(ctypes.c_int),
|
|
171
|
+
]
|
|
172
|
+
d.fd_get_size.restype = None
|
|
173
|
+
|
|
174
|
+
d.fd_release.argtypes = [ctypes.POINTER(_Ctx)]
|
|
175
|
+
d.fd_release.restype = None
|
|
176
|
+
|
|
177
|
+
d.fd_set_conf.argtypes = [ctypes.POINTER(_Ctx), ctypes.c_float]
|
|
178
|
+
d.fd_set_conf.restype = None
|
|
179
|
+
|
|
180
|
+
d.fd_set_classes.argtypes = [ctypes.POINTER(_Ctx), ctypes.POINTER(ctypes.c_int), ctypes.c_int]
|
|
181
|
+
d.fd_set_classes.restype = None
|
|
182
|
+
|
|
183
|
+
self._Det = _Det
|
|
184
|
+
|
|
185
|
+
# ── Public API ────────────────────────────────
|
|
186
|
+
|
|
187
|
+
def detect(self, image_rgb, conf: float = None, classes: List[int] = None) -> List[Detection]:
|
|
188
|
+
"""
|
|
189
|
+
Run inference on a single image.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
image_rgb: numpy array (H, W, 3) uint8 RGB.
|
|
193
|
+
conf: Override confidence threshold for this frame (None = keep current).
|
|
194
|
+
classes: Override target classes for this frame (None = keep current).
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
List of Detection objects.
|
|
198
|
+
"""
|
|
199
|
+
import numpy as np
|
|
200
|
+
if not isinstance(image_rgb, np.ndarray):
|
|
201
|
+
raise TypeError("image_rgb must be a numpy array")
|
|
202
|
+
if image_rgb.dtype != np.uint8:
|
|
203
|
+
image_rgb = image_rgb.astype(np.uint8)
|
|
204
|
+
if not image_rgb.flags["C_CONTIGUOUS"]:
|
|
205
|
+
image_rgb = np.ascontiguousarray(image_rgb)
|
|
206
|
+
|
|
207
|
+
if conf is not None:
|
|
208
|
+
self._dll.fd_set_conf(self._ctx, ctypes.c_float(conf))
|
|
209
|
+
if classes is not None:
|
|
210
|
+
n = len(classes)
|
|
211
|
+
c_cls = (ctypes.c_int * n)(*classes)
|
|
212
|
+
self._dll.fd_set_classes(self._ctx, c_cls, ctypes.c_int(n))
|
|
213
|
+
|
|
214
|
+
dets = (self._Det * 300)()
|
|
215
|
+
count = ctypes.c_int()
|
|
216
|
+
ptr = image_rgb.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))
|
|
217
|
+
ret = self._dll.fd_process(self._ctx, ptr, dets, 300, ctypes.byref(count))
|
|
218
|
+
if ret != 0:
|
|
219
|
+
raise RuntimeError(f"fd_process failed with code {ret}")
|
|
220
|
+
|
|
221
|
+
results = []
|
|
222
|
+
sx = self._src_w / self.input_width if self.resize_mode else 1.0
|
|
223
|
+
sy = self._src_h / self.input_height if self.resize_mode else 1.0
|
|
224
|
+
for i in range(count.value):
|
|
225
|
+
d = dets[i]
|
|
226
|
+
b = Detection(d.x1*sx, d.y1*sy, d.x2*sx, d.y2*sy, d.conf, d.class_id)
|
|
227
|
+
results.append(b)
|
|
228
|
+
return results
|
|
229
|
+
|
|
230
|
+
def __call__(self, image) -> List[Detection]:
|
|
231
|
+
"""Shortcut: engine(image) → detections"""
|
|
232
|
+
return self.detect(image)
|
|
233
|
+
|
|
234
|
+
def close(self):
|
|
235
|
+
"""Release GPU resources."""
|
|
236
|
+
if self._ctx:
|
|
237
|
+
self._dll.fd_release(self._ctx)
|
|
238
|
+
self._ctx = None
|
|
239
|
+
|
|
240
|
+
def __enter__(self):
|
|
241
|
+
return self
|
|
242
|
+
|
|
243
|
+
def __exit__(self, *args):
|
|
244
|
+
self.close()
|
|
245
|
+
|
|
246
|
+
def __del__(self):
|
|
247
|
+
"""Auto-release on garbage collection."""
|
|
248
|
+
try:
|
|
249
|
+
self.close()
|
|
250
|
+
except Exception:
|
|
251
|
+
pass
|
|
252
|
+
|
|
253
|
+
@property
|
|
254
|
+
def input_size(self) -> Tuple[int, int]:
|
|
255
|
+
return (self.input_height, self.input_width)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
# ── Module-level utilities ──────────────────────
|
|
259
|
+
|
|
260
|
+
def get_machine_id(sdk_dir: str = None) -> str:
|
|
261
|
+
"""
|
|
262
|
+
Get this machine's unique hardware ID for license generation.
|
|
263
|
+
|
|
264
|
+
Usage (first-time setup):
|
|
265
|
+
>>> import flashdetect
|
|
266
|
+
>>> print(flashdetect.get_machine_id())
|
|
267
|
+
A1B2C3D4E5F67890
|
|
268
|
+
|
|
269
|
+
Send this ID to the vendor to receive a license.key file,
|
|
270
|
+
then place it beside flashdetect.dll (in the same directory).
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
sdk_dir: Path to the directory containing flashdetect.dll.
|
|
274
|
+
Defaults to the package install directory.
|
|
275
|
+
Returns:
|
|
276
|
+
16-character hex machine ID string.
|
|
277
|
+
"""
|
|
278
|
+
if sdk_dir is None:
|
|
279
|
+
sdk_dir = os.path.dirname(os.path.abspath(__file__))
|
|
280
|
+
os.add_dll_directory(sdk_dir)
|
|
281
|
+
|
|
282
|
+
dll_path = os.path.join(sdk_dir, "flashdetect.dll")
|
|
283
|
+
if not os.path.exists(dll_path):
|
|
284
|
+
raise FileNotFoundError(f"flashdetect.dll not found in {sdk_dir}")
|
|
285
|
+
|
|
286
|
+
try:
|
|
287
|
+
dll = ctypes.CDLL(dll_path)
|
|
288
|
+
except OSError as e:
|
|
289
|
+
raise RuntimeError(
|
|
290
|
+
f"Cannot load flashdetect.dll — missing runtime DLLs.\n"
|
|
291
|
+
f" {e}\n"
|
|
292
|
+
f" Ensure CUDA 12.4 + TensorRT 11.0 are installed."
|
|
293
|
+
) from e
|
|
294
|
+
dll.fd_get_machine_id.argtypes = [ctypes.c_char_p, ctypes.c_int]
|
|
295
|
+
dll.fd_get_machine_id.restype = ctypes.c_int
|
|
296
|
+
|
|
297
|
+
buf = ctypes.create_string_buffer(32)
|
|
298
|
+
if dll.fd_get_machine_id(buf, 32) != 0:
|
|
299
|
+
raise RuntimeError("Failed to get machine ID")
|
|
300
|
+
return buf.value.decode("utf-8")
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def install_license(source_path: str, sdk_dir: str = None) -> str:
|
|
304
|
+
"""
|
|
305
|
+
Copy a license.key file into the flashdetect package directory.
|
|
306
|
+
|
|
307
|
+
Usage:
|
|
308
|
+
>>> import flashdetect
|
|
309
|
+
>>> flashdetect.install_license("C:/Users/me/Downloads/license.key")
|
|
310
|
+
|
|
311
|
+
This copies the file to the same directory as flashdetect.dll, where
|
|
312
|
+
the DLL looks for it at runtime.
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
source_path: Path to your license.key file.
|
|
316
|
+
sdk_dir: Target directory (default: flashdetect package dir).
|
|
317
|
+
Returns:
|
|
318
|
+
The destination path where license.key was installed.
|
|
319
|
+
"""
|
|
320
|
+
import shutil
|
|
321
|
+
|
|
322
|
+
if not os.path.exists(source_path):
|
|
323
|
+
raise FileNotFoundError(f"license.key not found at: {source_path}")
|
|
324
|
+
|
|
325
|
+
if sdk_dir is None:
|
|
326
|
+
sdk_dir = os.path.dirname(os.path.abspath(__file__))
|
|
327
|
+
|
|
328
|
+
dest_path = os.path.join(sdk_dir, "license.key")
|
|
329
|
+
|
|
330
|
+
if os.path.exists(dest_path):
|
|
331
|
+
print(f"[flashdetect] Replacing existing: {dest_path}")
|
|
332
|
+
|
|
333
|
+
shutil.copy2(source_path, dest_path)
|
|
334
|
+
print(f"[flashdetect] license.key installed → {dest_path}")
|
|
335
|
+
|
|
336
|
+
mid = get_machine_id(sdk_dir)
|
|
337
|
+
print(f"[flashdetect] Machine ID: {mid}")
|
|
338
|
+
|
|
339
|
+
return dest_path
|
|
Binary file
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flashdetect-cu124
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Low-latency YOLO26 TensorRT inference for real-time video streams
|
|
5
|
+
Home-page: https://github.com/toever/flashdetect
|
|
6
|
+
Classifier: Development Status :: 3 - Alpha
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: License :: Other/Proprietary License
|
|
9
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
10
|
+
Classifier: Environment :: GPU :: NVIDIA CUDA
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: numpy>=1.21
|
|
17
|
+
Requires-Dist: tensorrt-cu12
|
|
18
|
+
Requires-Dist: nvidia-cuda-runtime-cu12
|
|
19
|
+
Requires-Dist: nvidia-cublas-cu12
|
|
20
|
+
Dynamic: classifier
|
|
21
|
+
Dynamic: description
|
|
22
|
+
Dynamic: description-content-type
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
# FlashDetect
|
|
29
|
+
|
|
30
|
+
**低延迟 YOLO26 目标检测推理引擎,专为实时视频流优化。仅支持 YOLO26 端到端导出(`[N,6]` 格式,无 NMS)。**
|
|
31
|
+
|
|
32
|
+
基于 TensorRT + CUDA Graph,全 GPU 流水线。
|
|
33
|
+
|
|
34
|
+
## 安装
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install flashdetect-cu124
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 系统要求
|
|
41
|
+
|
|
42
|
+
- Windows x64
|
|
43
|
+
- NVIDIA GPU (Compute Capability ≥ 7.0)
|
|
44
|
+
- Python ≥ 3.8
|
|
45
|
+
|
|
46
|
+
运行时依赖自动安装(CUDA 12.4 + TensorRT 11.x)。
|
|
47
|
+
|
|
48
|
+
## 激活授权
|
|
49
|
+
|
|
50
|
+
本 SDK 需要硬件绑定授权,首次使用:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
import flashdetect
|
|
54
|
+
|
|
55
|
+
# 1. 获取本机 ID,发送给供应商
|
|
56
|
+
print(flashdetect.get_machine_id())
|
|
57
|
+
|
|
58
|
+
# 2. 收到 license.key 后,一键安装
|
|
59
|
+
flashdetect.install_license("C:/Users/me/Downloads/license.key")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
激活后即可正常使用。
|
|
63
|
+
|
|
64
|
+
## 快速开始
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from flashdetect import FlashDetect
|
|
68
|
+
|
|
69
|
+
# 加载模型(支持 with 语句自动释放)
|
|
70
|
+
with FlashDetect("yolo26n.engine", conf=0.25) as detector:
|
|
71
|
+
frame = camera.read() # (H, W, 3) BGR uint8
|
|
72
|
+
dets = detector.detect(frame)
|
|
73
|
+
|
|
74
|
+
for d in dets:
|
|
75
|
+
print(f" cls={d.class_id} conf={d.conf:.2f} "
|
|
76
|
+
f"({d.x1:.0f},{d.y1:.0f})-({d.x2:.0f},{d.y2:.0f})")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## API 参考
|
|
80
|
+
|
|
81
|
+
### 模块级工具
|
|
82
|
+
|
|
83
|
+
| 函数 | 说明 |
|
|
84
|
+
|------|------|
|
|
85
|
+
| `flashdetect.get_machine_id()` | 获取本机硬件 ID(用于申请授权) |
|
|
86
|
+
| `flashdetect.install_license(path)` | 安装 license.key 到正确位置 |
|
|
87
|
+
|
|
88
|
+
### `FlashDetect(engine_path, **kwargs)`
|
|
89
|
+
|
|
90
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
91
|
+
|------|------|--------|------|
|
|
92
|
+
| `engine_path` | `str` | 必填 | TensorRT .engine 文件路径 |
|
|
93
|
+
| `conf` | `float` | `0.25` | 置信度阈值 |
|
|
94
|
+
| `device_id` | `int` | `0` | GPU 设备编号 |
|
|
95
|
+
| `target_classes` | `List[int]` | `None` | 只检测指定类别(None=全部) |
|
|
96
|
+
| `max_dets` | `int` | `0` | 最大检测数(0=引擎默认) |
|
|
97
|
+
| `format` | `str` | `"BGR"` | 输入颜色格式:`"BGR"` 或 `"RGB"` |
|
|
98
|
+
| `resize_mode` | `int` | `0` | 0=不缩放,1=GPU 缩放至引擎尺寸 |
|
|
99
|
+
| `src_w` | `int` | `0` | 源图像宽度(resize_mode=1 时必填) |
|
|
100
|
+
| `src_h` | `int` | `0` | 源图像高度(resize_mode=1 时必填) |
|
|
101
|
+
|
|
102
|
+
### `detect(image, conf=None, classes=None) -> List[Detection]`
|
|
103
|
+
|
|
104
|
+
| 参数 | 类型 | 说明 |
|
|
105
|
+
|------|------|------|
|
|
106
|
+
| `image` | `np.ndarray` | (H, W, 3) uint8 图像 |
|
|
107
|
+
| `conf` | `float` | 可选,覆盖当前帧的置信度阈值 |
|
|
108
|
+
| `classes` | `List[int]` | 可选,覆盖当前帧的目标类别 |
|
|
109
|
+
|
|
110
|
+
### `Detection`
|
|
111
|
+
|
|
112
|
+
| 属性 | 类型 | 说明 |
|
|
113
|
+
|------|------|------|
|
|
114
|
+
| `x1, y1, x2, y2` | `float` | 边界框坐标 |
|
|
115
|
+
| `conf` | `float` | 置信度 |
|
|
116
|
+
| `class_id` | `int` | 类别 ID |
|
|
117
|
+
| `xyxy` | `tuple` | `(x1, y1, x2, y2)` 快捷属性 |
|
|
118
|
+
|
|
119
|
+
### 其他方法
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
detector.input_width, detector.input_height # 引擎输入尺寸
|
|
123
|
+
detector.close() # 释放 GPU 资源
|
|
124
|
+
# 或使用 with 语句自动释放:
|
|
125
|
+
# with FlashDetect("model.engine") as detector:
|
|
126
|
+
# dets = detector.detect(frame)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 性能
|
|
130
|
+
|
|
131
|
+
待测试
|
|
132
|
+
|
|
133
|
+
CUDA Graph 确保每次推理耗时稳定,无 CPU 端开销。
|
|
134
|
+
|
|
135
|
+
## 适用场景
|
|
136
|
+
|
|
137
|
+
- 游戏画面实时分析(DX 采集)
|
|
138
|
+
- 工业相机检测
|
|
139
|
+
- 视频流目标跟踪
|
|
140
|
+
|
|
141
|
+
**不适用**:图片文件批量识别(无需 GPU Graph 优化)。
|
|
142
|
+
|
|
143
|
+
## 许可 & 联系
|
|
144
|
+
|
|
145
|
+
本 SDK 需硬件绑定授权,每台机器独立 `license.key`。
|
|
146
|
+
无有效授权时,`FlashDetect()` 会抛出异常并显示本机 ID。
|
|
147
|
+
|
|
148
|
+
获取授权请联系:
|
|
149
|
+
|
|
150
|
+
- 📧 邮箱:`2169431623@qq.com` / `wut815318@gmail.com`
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
flashdetect/__init__.py,sha256=p7JADJvCDj5NTh67tdFUdEhoIxy69v7TmcWH4bNwIjo,12164
|
|
2
|
+
flashdetect/flashdetect.dll,sha256=yFXtV5sTJLBT7avHYP3TVXDUfkVyR2QE-jTBZ51jdb4,78336
|
|
3
|
+
flashdetect_cu124-1.0.0.dist-info/METADATA,sha256=O-arKuIHRSelAPZdehUNht2cImQNLQzKAbIRNFF4NMQ,4567
|
|
4
|
+
flashdetect_cu124-1.0.0.dist-info/WHEEL,sha256=QR8DNjG6Lr6bNErJWJgF4dP2dJ2N7NpY-BWly1OvcTM,97
|
|
5
|
+
flashdetect_cu124-1.0.0.dist-info/top_level.txt,sha256=FCzr5dABchxs3JZZRINKHH6sKMM5s1w-K5rHy3MLy5E,12
|
|
6
|
+
flashdetect_cu124-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
flashdetect
|