Files
frigate/frigate/detectors/detection_api.py
T
Nicolas MowenandGitHub 5e2c59d27d Dynamically install and load detector dependencies (#24156)
* Dynamically install and load detector dependencies

* Cleanup

* Cleanup
2026-09-02 08:49:52 -05:00

80 lines
2.8 KiB
Python

import logging
from abc import ABC, abstractmethod
from typing import ClassVar
import numpy as np
from frigate.detectors.detector_config import BaseDetectorConfig, ModelTypeEnum
from frigate.util.runtime_deps import RuntimeManifest, activate, ensure_installed
logger = logging.getLogger(__name__)
class DetectionApi(ABC):
type_key: str
supported_models: list[ModelTypeEnum]
# pinned SDK artifacts that are installed at runtime instead of being
# shipped in the image; None when the runtime is already available
runtime_manifest: ClassVar[RuntimeManifest | None] = None
@abstractmethod
def __init__(self, detector_config: BaseDetectorConfig):
self.detector_config = detector_config
self.thresh = 0.4
self.height = detector_config.model.height
self.width = detector_config.model.width
@abstractmethod
def detect_raw(self, tensor_input):
pass
@classmethod
def ensure_dependencies(cls) -> None:
"""Download and install this detector's runtime if it is not present.
Runs once in the main process before detector processes start, so a
single install serves every process and the user site is on sys.path
before it is inherited.
"""
if cls.runtime_manifest is not None:
ensure_installed(cls.runtime_manifest)
@classmethod
def activate_dependencies(cls) -> None:
"""Make the installed runtime importable in the current process."""
if cls.runtime_manifest is not None:
activate(cls.runtime_manifest)
def calculate_grids_strides(self, expanded=True) -> None:
grids = []
expanded_strides = []
# decode and orient predictions
strides = [8, 16, 32]
hsizes = [self.height // stride for stride in strides]
wsizes = [self.width // stride for stride in strides]
for hsize, wsize, stride in zip(hsizes, wsizes, strides):
xv, yv = np.meshgrid(np.arange(wsize), np.arange(hsize))
if expanded:
grid = np.stack((xv, yv), 2).reshape(1, -1, 2)
grids.append(grid)
shape = grid.shape[:2]
expanded_strides.append(np.full((*shape, 1), stride))
else:
xv = xv.reshape(1, 1, hsize, wsize)
yv = yv.reshape(1, 1, hsize, wsize)
grids.extend(np.concatenate((xv, yv), axis=1).tolist())
expanded_strides.extend(
np.array([stride, stride]).reshape(1, 2, 1, 1).tolist()
)
if expanded:
self.grids = np.concatenate(grids, 1)
self.expanded_strides = np.concatenate(expanded_strides, 1)
else:
self.grids = grids
self.expanded_strides = expanded_strides