mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-18 07:29:45 +00:00
perf(axelera): greedy NMS via cv2.dnn.NMSBoxes
Replace the pure-Python O(n^2) _nms_xyxy loop with the framework's own C++ NMS (xyxy -> xywh first, same as frigate.util.model). Same contract: kept indices in descending score order; empty-safe. Removes a per-frame CPU hot spot on dense daytime frames without changing decode results.
This commit is contained in:
parent
0d0581494f
commit
97705e7df2
@ -174,28 +174,39 @@ def _find_model_json(where: str) -> str:
|
||||
)
|
||||
|
||||
|
||||
def _nms_xyxy(boxes, scores, iou_threshold: float) -> list:
|
||||
"""Classic greedy NMS on xyxy boxes. Returns kept indices (desc score)."""
|
||||
def _nms_xyxy(boxes, scores, iou_threshold: float) -> np.ndarray:
|
||||
"""Greedy NMS on xyxy boxes via cv2.dnn.NMSBoxes (C++, GIL-free).
|
||||
|
||||
Returns kept indices in descending score order, same contract as the
|
||||
previous pure-Python loop but without the O(n^2) worst case on dense
|
||||
frames (daytime, multiple motion regions at 48 fps offered).
|
||||
"""
|
||||
if len(boxes) == 0:
|
||||
return []
|
||||
x1, y1, x2, y2 = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]
|
||||
areas = np.maximum(0, x2 - x1) * np.maximum(0, y2 - y1)
|
||||
order = scores.argsort()[::-1]
|
||||
keep = []
|
||||
while order.size > 0:
|
||||
i = order[0]
|
||||
keep.append(int(i))
|
||||
if order.size == 1:
|
||||
break
|
||||
xx1 = np.maximum(x1[i], x1[order[1:]])
|
||||
yy1 = np.maximum(y1[i], y1[order[1:]])
|
||||
xx2 = np.minimum(x2[i], x2[order[1:]])
|
||||
yy2 = np.minimum(y2[i], y2[order[1:]])
|
||||
inter = np.maximum(0, xx2 - xx1) * np.maximum(0, yy2 - yy1)
|
||||
union = areas[i] + areas[order[1:]] - inter
|
||||
ovr = np.where(union > 0, inter / np.maximum(union, 1e-9), 0)
|
||||
order = order[1:][ovr <= iou_threshold]
|
||||
return keep
|
||||
return np.array([], dtype=np.int64)
|
||||
x1 = boxes[:, 0]
|
||||
y1 = boxes[:, 1]
|
||||
xywh = np.stack(
|
||||
[
|
||||
x1,
|
||||
y1,
|
||||
np.maximum(0, boxes[:, 2] - x1),
|
||||
np.maximum(0, boxes[:, 3] - y1),
|
||||
],
|
||||
axis=1,
|
||||
)
|
||||
indices = cv2.dnn.NMSBoxes(
|
||||
xywh.tolist(),
|
||||
[float(s) for s in scores],
|
||||
# inputs are already filtered above CONF_THRESHOLD by the caller
|
||||
score_threshold=0.0,
|
||||
nms_threshold=float(iou_threshold),
|
||||
)
|
||||
if len(indices) == 0:
|
||||
return np.array([], dtype=np.int64)
|
||||
if isinstance(indices, np.ndarray):
|
||||
return indices.reshape(-1).astype(np.int64)
|
||||
# OpenCV versions that return a (N, 1) list of nested lists
|
||||
return np.asarray(indices, dtype=np.int64).reshape(-1)
|
||||
|
||||
|
||||
def _read_model_manifest(model_dir: str) -> dict:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user