mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-06 14:52:47 +03:00
use camera config for autotracking enabled state
Camera processes read autotracking state from a shared `autotracker_enabled` value that the dispatcher and autotracker had to keep in sync with the config by hand. Camera processes now subscribe to the `autotracking` and `onvif` config updates and read `onvif.autotracking.enabled` directly, so the shared value and the autotracker's mirroring method are gone. `_disable` now publishes its change so the camera process hears about it. Also removes `tracking_active`, which was set and cleared but never read.
This commit is contained in:
+1
-5
@@ -166,11 +166,7 @@ class FrigateApp:
|
|||||||
# create camera_metrics
|
# create camera_metrics
|
||||||
for camera_name in self.config.cameras.keys():
|
for camera_name in self.config.cameras.keys():
|
||||||
self.camera_metrics[camera_name] = CameraMetrics(self.metrics_manager)
|
self.camera_metrics[camera_name] = CameraMetrics(self.metrics_manager)
|
||||||
self.ptz_metrics[camera_name] = PTZMetrics(
|
self.ptz_metrics[camera_name] = PTZMetrics()
|
||||||
autotracker_enabled=self.config.cameras[
|
|
||||||
camera_name
|
|
||||||
].onvif.autotracking.enabled
|
|
||||||
)
|
|
||||||
|
|
||||||
def init_queues(self) -> None:
|
def init_queues(self) -> None:
|
||||||
# Queue for cameras to push tracked objects to
|
# Queue for cameras to push tracked objects to
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ class CameraMetrics:
|
|||||||
|
|
||||||
|
|
||||||
class PTZMetrics:
|
class PTZMetrics:
|
||||||
autotracker_enabled: Synchronized
|
|
||||||
|
|
||||||
start_time: Synchronized
|
start_time: Synchronized
|
||||||
stop_time: Synchronized
|
stop_time: Synchronized
|
||||||
frame_time: Synchronized
|
frame_time: Synchronized
|
||||||
@@ -52,13 +50,10 @@ class PTZMetrics:
|
|||||||
max_zoom: Synchronized
|
max_zoom: Synchronized
|
||||||
min_zoom: Synchronized
|
min_zoom: Synchronized
|
||||||
|
|
||||||
tracking_active: Event
|
|
||||||
motor_stopped: Event
|
motor_stopped: Event
|
||||||
reset: Event
|
reset: Event
|
||||||
|
|
||||||
def __init__(self, *, autotracker_enabled: bool):
|
def __init__(self) -> None:
|
||||||
self.autotracker_enabled = mp.Value("i", autotracker_enabled) # type: ignore[assignment]
|
|
||||||
|
|
||||||
self.start_time = mp.Value("d", 0) # type: ignore[assignment]
|
self.start_time = mp.Value("d", 0) # type: ignore[assignment]
|
||||||
self.stop_time = mp.Value("d", 0) # type: ignore[assignment]
|
self.stop_time = mp.Value("d", 0) # type: ignore[assignment]
|
||||||
self.frame_time = mp.Value("d", 0) # type: ignore[assignment]
|
self.frame_time = mp.Value("d", 0) # type: ignore[assignment]
|
||||||
@@ -66,7 +61,6 @@ class PTZMetrics:
|
|||||||
self.max_zoom = mp.Value("d", 0) # type: ignore[assignment]
|
self.max_zoom = mp.Value("d", 0) # type: ignore[assignment]
|
||||||
self.min_zoom = mp.Value("d", 0) # type: ignore[assignment]
|
self.min_zoom = mp.Value("d", 0) # type: ignore[assignment]
|
||||||
|
|
||||||
self.tracking_active = mp.Event()
|
|
||||||
self.motor_stopped = mp.Event()
|
self.motor_stopped = mp.Event()
|
||||||
self.reset = mp.Event()
|
self.reset = mp.Event()
|
||||||
|
|
||||||
|
|||||||
@@ -120,9 +120,7 @@ class CameraMaintainer(threading.Thread):
|
|||||||
|
|
||||||
if runtime:
|
if runtime:
|
||||||
self.camera_metrics[name] = CameraMetrics(self.metrics_manager)
|
self.camera_metrics[name] = CameraMetrics(self.metrics_manager)
|
||||||
self.ptz_metrics[name] = PTZMetrics(
|
self.ptz_metrics[name] = PTZMetrics()
|
||||||
autotracker_enabled=config.onvif.autotracking.enabled
|
|
||||||
)
|
|
||||||
self.region_grids[name] = get_camera_regions_grid(
|
self.region_grids[name] = get_camera_regions_grid(
|
||||||
name,
|
name,
|
||||||
config.detect,
|
config.detect,
|
||||||
|
|||||||
@@ -759,15 +759,13 @@ class Dispatcher:
|
|||||||
"Autotracking must be enabled in the config to be turned on via MQTT."
|
"Autotracking must be enabled in the config to be turned on via MQTT."
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
if not self.ptz_metrics[camera_name].autotracker_enabled.value:
|
if not ptz_autotracker_settings.enabled:
|
||||||
logger.info(f"Turning on ptz autotracker for {camera_name}")
|
logger.info(f"Turning on ptz autotracker for {camera_name}")
|
||||||
self.ptz_metrics[camera_name].autotracker_enabled.value = True
|
|
||||||
self.ptz_metrics[camera_name].start_time.value = 0
|
self.ptz_metrics[camera_name].start_time.value = 0
|
||||||
ptz_autotracker_settings.enabled = True
|
ptz_autotracker_settings.enabled = True
|
||||||
elif payload == "OFF":
|
elif payload == "OFF":
|
||||||
if self.ptz_metrics[camera_name].autotracker_enabled.value:
|
if ptz_autotracker_settings.enabled:
|
||||||
logger.info(f"Turning off ptz autotracker for {camera_name}")
|
logger.info(f"Turning off ptz autotracker for {camera_name}")
|
||||||
self.ptz_metrics[camera_name].autotracker_enabled.value = False
|
|
||||||
self.ptz_metrics[camera_name].start_time.value = 0
|
self.ptz_metrics[camera_name].start_time.value = 0
|
||||||
ptz_autotracker_settings.enabled = False
|
ptz_autotracker_settings.enabled = False
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class ImprovedMotionDetector(MotionDetector):
|
|||||||
config: RuntimeMotionConfig,
|
config: RuntimeMotionConfig,
|
||||||
fps: int,
|
fps: int,
|
||||||
ptz_metrics: PTZMetrics | None = None,
|
ptz_metrics: PTZMetrics | None = None,
|
||||||
|
autotracking_enabled: bool = False,
|
||||||
name: str = "improved",
|
name: str = "improved",
|
||||||
blur_radius: int = 1,
|
blur_radius: int = 1,
|
||||||
interpolation: int = cv2.INTER_NEAREST,
|
interpolation: int = cv2.INTER_NEAREST,
|
||||||
@@ -45,6 +46,7 @@ class ImprovedMotionDetector(MotionDetector):
|
|||||||
self.contrast_values[:, 1:2] = 255
|
self.contrast_values[:, 1:2] = 255
|
||||||
self.contrast_values_index = 0
|
self.contrast_values_index = 0
|
||||||
self.ptz_metrics = ptz_metrics
|
self.ptz_metrics = ptz_metrics
|
||||||
|
self.autotracking_enabled = autotracking_enabled
|
||||||
self.last_stop_time: float | None = None
|
self.last_stop_time: float | None = None
|
||||||
|
|
||||||
def is_calibrating(self) -> bool:
|
def is_calibrating(self) -> bool:
|
||||||
@@ -59,8 +61,7 @@ class ImprovedMotionDetector(MotionDetector):
|
|||||||
# if ptz motor is moving from autotracking, quickly return
|
# if ptz motor is moving from autotracking, quickly return
|
||||||
# a single box that is 80% of the frame
|
# a single box that is 80% of the frame
|
||||||
if self.ptz_metrics is not None and (
|
if self.ptz_metrics is not None and (
|
||||||
self.ptz_metrics.autotracker_enabled.value
|
self.autotracking_enabled and not self.ptz_metrics.motor_stopped.is_set()
|
||||||
and not self.ptz_metrics.motor_stopped.is_set()
|
|
||||||
):
|
):
|
||||||
return [
|
return [
|
||||||
(
|
(
|
||||||
@@ -162,7 +163,7 @@ class ImprovedMotionDetector(MotionDetector):
|
|||||||
# if so, reassign the average to the current frame so we begin with a new baseline
|
# if so, reassign the average to the current frame so we begin with a new baseline
|
||||||
if self.ptz_metrics is not None and (
|
if self.ptz_metrics is not None and (
|
||||||
# ensure we only do this for cameras with autotracking enabled
|
# ensure we only do this for cameras with autotracking enabled
|
||||||
self.ptz_metrics.autotracker_enabled.value
|
self.autotracking_enabled
|
||||||
and self.ptz_metrics.motor_stopped.is_set()
|
and self.ptz_metrics.motor_stopped.is_set()
|
||||||
and (
|
and (
|
||||||
self.last_stop_time is None
|
self.last_stop_time is None
|
||||||
|
|||||||
+10
-29
@@ -23,6 +23,7 @@ from frigate.config import CameraConfig, FrigateConfig, ZoomingModeEnum
|
|||||||
from frigate.config.camera.updater import (
|
from frigate.config.camera.updater import (
|
||||||
CameraConfigUpdateEnum,
|
CameraConfigUpdateEnum,
|
||||||
CameraConfigUpdateSubscriber,
|
CameraConfigUpdateSubscriber,
|
||||||
|
CameraConfigUpdateTopic,
|
||||||
)
|
)
|
||||||
from frigate.const import (
|
from frigate.const import (
|
||||||
AUTOTRACKING_MAX_AREA_RATIO,
|
AUTOTRACKING_MAX_AREA_RATIO,
|
||||||
@@ -236,7 +237,7 @@ class PtzAutoTracker(threading.Thread):
|
|||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
while not self.stop_event.wait(1):
|
while not self.stop_event.wait(1):
|
||||||
self.check_for_updates()
|
self.config_subscriber.check_for_updates()
|
||||||
|
|
||||||
for camera, camera_config in list(self.config.cameras.items()):
|
for camera, camera_config in list(self.config.cameras.items()):
|
||||||
if not camera_config.enabled:
|
if not camera_config.enabled:
|
||||||
@@ -257,29 +258,6 @@ class PtzAutoTracker(threading.Thread):
|
|||||||
self.config_subscriber.stop()
|
self.config_subscriber.stop()
|
||||||
logger.info("Exiting autotracker...")
|
logger.info("Exiting autotracker...")
|
||||||
|
|
||||||
def check_for_updates(self) -> None:
|
|
||||||
"""Apply camera config updates and mirror autotracking state to ptz metrics.
|
|
||||||
|
|
||||||
The camera processes read autotracker_enabled rather than the config, so it
|
|
||||||
has to follow every path that can change autotracking, not just the mqtt
|
|
||||||
toggle that writes it directly.
|
|
||||||
"""
|
|
||||||
updates = self.config_subscriber.check_for_updates()
|
|
||||||
|
|
||||||
for cameras in updates.values():
|
|
||||||
for camera in cameras:
|
|
||||||
camera_config = self.config.cameras.get(camera)
|
|
||||||
metrics = self.ptz_metrics.get(camera)
|
|
||||||
|
|
||||||
# a camera added at runtime gets its metrics from the maintainer on
|
|
||||||
# another thread, which seeds them from this same config value
|
|
||||||
if camera_config is None or metrics is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
metrics.autotracker_enabled.value = (
|
|
||||||
camera_config.onvif.autotracking.enabled
|
|
||||||
)
|
|
||||||
|
|
||||||
async def _autotracker_setup(self, camera_config: CameraConfig, camera: str):
|
async def _autotracker_setup(self, camera_config: CameraConfig, camera: str):
|
||||||
logger.debug(f"{camera}: Autotracker init")
|
logger.debug(f"{camera}: Autotracker init")
|
||||||
|
|
||||||
@@ -337,14 +315,19 @@ class PtzAutoTracker(threading.Thread):
|
|||||||
if camera_config.onvif.autotracking.calibrate_on_startup:
|
if camera_config.onvif.autotracking.calibrate_on_startup:
|
||||||
await self._calibrate_camera(camera)
|
await self._calibrate_camera(camera)
|
||||||
|
|
||||||
self.ptz_metrics[camera].tracking_active.clear()
|
|
||||||
self.dispatcher.publish(f"{camera}/ptz_autotracker/active", "OFF", retain=False)
|
self.dispatcher.publish(f"{camera}/ptz_autotracker/active", "OFF", retain=False)
|
||||||
self.autotracker_init[camera] = True
|
self.autotracker_init[camera] = True
|
||||||
|
|
||||||
def _disable(self, camera: str, reason: str) -> None:
|
def _disable(self, camera: str, reason: str) -> None:
|
||||||
logger.warning(f"Disabling autotracking for {camera}: {reason}")
|
logger.warning(f"Disabling autotracking for {camera}: {reason}")
|
||||||
self.config.cameras[camera].onvif.autotracking.enabled = False
|
autotracking_config = self.config.cameras[camera].onvif.autotracking
|
||||||
self.ptz_metrics[camera].autotracker_enabled.value = False
|
autotracking_config.enabled = False
|
||||||
|
|
||||||
|
# the camera process holds its own copy of the config
|
||||||
|
self.dispatcher.config_updater.publish_update(
|
||||||
|
CameraConfigUpdateTopic(CameraConfigUpdateEnum.autotracking, camera),
|
||||||
|
autotracking_config,
|
||||||
|
)
|
||||||
|
|
||||||
def _reset_tracked_object_metrics(self, camera: str) -> None:
|
def _reset_tracked_object_metrics(self, camera: str) -> None:
|
||||||
zoom_factor = self.config.cameras[camera].onvif.autotracking.zoom_factor
|
zoom_factor = self.config.cameras[camera].onvif.autotracking.zoom_factor
|
||||||
@@ -1307,7 +1290,6 @@ class PtzAutoTracker(threading.Thread):
|
|||||||
logger.debug(
|
logger.debug(
|
||||||
f"{camera}: New object: {obj.obj_data['id']} {obj.obj_data['box']} {obj.obj_data['frame_time']}"
|
f"{camera}: New object: {obj.obj_data['id']} {obj.obj_data['box']} {obj.obj_data['frame_time']}"
|
||||||
)
|
)
|
||||||
self.ptz_metrics[camera].tracking_active.set()
|
|
||||||
self.dispatcher.publish(
|
self.dispatcher.publish(
|
||||||
f"{camera}/ptz_autotracker/active", "ON", retain=False
|
f"{camera}/ptz_autotracker/active", "ON", retain=False
|
||||||
)
|
)
|
||||||
@@ -1441,7 +1423,6 @@ class PtzAutoTracker(threading.Thread):
|
|||||||
# update stored zoom level from preset
|
# update stored zoom level from preset
|
||||||
await self._wait_until_stopped(camera)
|
await self._wait_until_stopped(camera)
|
||||||
|
|
||||||
self.ptz_metrics[camera].tracking_active.clear()
|
|
||||||
self.dispatcher.publish(
|
self.dispatcher.publish(
|
||||||
f"{camera}/ptz_autotracker/active", "OFF", retain=False
|
f"{camera}/ptz_autotracker/active", "OFF", retain=False
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -566,8 +566,9 @@ class OnvifController:
|
|||||||
return
|
return
|
||||||
|
|
||||||
metrics = self.ptz_metrics.get(camera_name)
|
metrics = self.ptz_metrics.get(camera_name)
|
||||||
|
camera_config = self.config.cameras.get(camera_name)
|
||||||
|
|
||||||
if metrics is None:
|
if metrics is None or camera_config is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
@@ -583,7 +584,7 @@ class OnvifController:
|
|||||||
cam["active"] = True
|
cam["active"] = True
|
||||||
|
|
||||||
# only track start_time for autotracking
|
# only track start_time for autotracking
|
||||||
if metrics.autotracker_enabled.value:
|
if camera_config.onvif.autotracking.enabled:
|
||||||
metrics.motor_stopped.clear()
|
metrics.motor_stopped.clear()
|
||||||
logger.debug(f"{camera_name}: PTZ start time: {metrics.frame_time.value}")
|
logger.debug(f"{camera_name}: PTZ start time: {metrics.frame_time.value}")
|
||||||
metrics.start_time.value = metrics.frame_time.value
|
metrics.start_time.value = metrics.frame_time.value
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ class TestImprovedMotionDetector(unittest.TestCase):
|
|||||||
|
|
||||||
class DummyPTZ:
|
class DummyPTZ:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.autotracker_enabled = _Stub(False)
|
|
||||||
self.motor_stopped = _Stub(False)
|
self.motor_stopped = _Stub(False)
|
||||||
self.stop_time = _Stub(0)
|
self.stop_time = _Stub(0)
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ KeyError on the autotracker thread or silently keep the wrong state:
|
|||||||
|
|
||||||
- autotracker_init only got an entry for cameras enabled when PtzAutoTracker was
|
- autotracker_init only got an entry for cameras enabled when PtzAutoTracker was
|
||||||
constructed, so runtime-enabled cameras raised KeyError on lookup.
|
constructed, so runtime-enabled cameras raised KeyError on lookup.
|
||||||
- ptz_metrics autotracker_enabled is what the camera processes read, but nothing
|
- _disable only changed the main process config, so the camera process kept
|
||||||
updated it when autotracking was enabled through a config save, so it stayed
|
running its motion estimator for a camera that could not autotrack.
|
||||||
False and the tracker never built a motion estimator.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
@@ -17,6 +16,7 @@ from unittest.mock import MagicMock
|
|||||||
|
|
||||||
from frigate.camera import PTZMetrics
|
from frigate.camera import PTZMetrics
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import FrigateConfig
|
||||||
|
from frigate.config.camera.updater import CameraConfigUpdateEnum
|
||||||
from frigate.ptz.autotrack import PtzAutoTracker
|
from frigate.ptz.autotrack import PtzAutoTracker
|
||||||
|
|
||||||
CAMERA = "ptz_cam"
|
CAMERA = "ptz_cam"
|
||||||
@@ -53,8 +53,9 @@ def _make_tracker(autotracking_enabled: bool = True) -> PtzAutoTracker:
|
|||||||
onvif over the network. Only the config/metrics state is relevant here."""
|
onvif over the network. Only the config/metrics state is relevant here."""
|
||||||
tracker = PtzAutoTracker.__new__(PtzAutoTracker)
|
tracker = PtzAutoTracker.__new__(PtzAutoTracker)
|
||||||
tracker.config = _config(autotracking_enabled)
|
tracker.config = _config(autotracking_enabled)
|
||||||
tracker.ptz_metrics = {CAMERA: PTZMetrics(autotracker_enabled=False)}
|
tracker.ptz_metrics = {CAMERA: PTZMetrics()}
|
||||||
tracker.onvif = MagicMock()
|
tracker.onvif = MagicMock()
|
||||||
|
tracker.dispatcher = MagicMock()
|
||||||
tracker.config_subscriber = MagicMock()
|
tracker.config_subscriber = MagicMock()
|
||||||
tracker.autotracker_init = {}
|
tracker.autotracker_init = {}
|
||||||
tracker.calibrating = {}
|
tracker.calibrating = {}
|
||||||
@@ -105,47 +106,21 @@ class TestAutotrackerEnqueueMove(unittest.TestCase):
|
|||||||
self._enqueue(0, 0, 0).assert_not_called()
|
self._enqueue(0, 0, 0).assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
class TestAutotrackerMetricSync(unittest.TestCase):
|
class TestAutotrackerDisable(unittest.TestCase):
|
||||||
def test_metric_follows_config_when_enabled_by_update(self) -> None:
|
def test_disable_publishes_to_camera_process(self) -> None:
|
||||||
# autotracking enabled via a config save: the metric was seeded False when
|
|
||||||
# the camera was added and nothing else updates it
|
|
||||||
tracker = _make_tracker(autotracking_enabled=True)
|
tracker = _make_tracker(autotracking_enabled=True)
|
||||||
metrics = tracker.ptz_metrics[CAMERA]
|
|
||||||
self.assertFalse(metrics.autotracker_enabled.value)
|
|
||||||
|
|
||||||
tracker.config_subscriber.check_for_updates.return_value = {"onvif": [CAMERA]}
|
tracker._disable(CAMERA, "onvif connection failed")
|
||||||
tracker.check_for_updates()
|
|
||||||
|
|
||||||
self.assertTrue(metrics.autotracker_enabled.value)
|
autotracking = tracker.config.cameras[CAMERA].onvif.autotracking
|
||||||
|
self.assertFalse(autotracking.enabled)
|
||||||
|
|
||||||
def test_metric_follows_config_when_disabled_by_update(self) -> None:
|
publish = tracker.dispatcher.config_updater.publish_update
|
||||||
tracker = _make_tracker(autotracking_enabled=False)
|
publish.assert_called_once()
|
||||||
metrics = tracker.ptz_metrics[CAMERA]
|
topic, payload = publish.call_args.args
|
||||||
metrics.autotracker_enabled.value = True
|
self.assertEqual(topic.update_type, CameraConfigUpdateEnum.autotracking)
|
||||||
|
self.assertEqual(topic.camera, CAMERA)
|
||||||
tracker.config_subscriber.check_for_updates.return_value = {
|
self.assertIs(payload, autotracking)
|
||||||
"autotracking": [CAMERA]
|
|
||||||
}
|
|
||||||
tracker.check_for_updates()
|
|
||||||
|
|
||||||
self.assertFalse(metrics.autotracker_enabled.value)
|
|
||||||
|
|
||||||
def test_metric_sync_skips_camera_without_metrics(self) -> None:
|
|
||||||
# `add` reaches the maintainer and the autotracker on separate threads with
|
|
||||||
# no ordering guarantee, so the metrics may not exist yet
|
|
||||||
tracker = _make_tracker()
|
|
||||||
tracker.ptz_metrics = {}
|
|
||||||
tracker.config_subscriber.check_for_updates.return_value = {"add": [CAMERA]}
|
|
||||||
|
|
||||||
tracker.check_for_updates()
|
|
||||||
|
|
||||||
def test_metric_sync_skips_unknown_camera(self) -> None:
|
|
||||||
tracker = _make_tracker()
|
|
||||||
tracker.config_subscriber.check_for_updates.return_value = {
|
|
||||||
"add": ["not_in_config"]
|
|
||||||
}
|
|
||||||
|
|
||||||
tracker.check_for_updates()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -121,9 +121,7 @@ def _make_move_controller(autotracking_enabled: bool) -> OnvifController:
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
controller.ptz_metrics = {
|
controller.ptz_metrics = {CAMERA: PTZMetrics()}
|
||||||
CAMERA: PTZMetrics(autotracker_enabled=autotracking_enabled)
|
|
||||||
}
|
|
||||||
return controller
|
return controller
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ class NorfairTracker(ObjectTracker):
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.ptz_metrics.autotracker_enabled.value:
|
if self.camera_config.onvif.autotracking.enabled:
|
||||||
self.ptz_motion_estimator = PtzMotionEstimator(
|
self.ptz_motion_estimator = PtzMotionEstimator(
|
||||||
self.camera_config, self.ptz_metrics
|
self.camera_config, self.ptz_metrics
|
||||||
)
|
)
|
||||||
@@ -515,7 +515,7 @@ class NorfairTracker(ObjectTracker):
|
|||||||
yuv_frame: np.ndarray | None = None
|
yuv_frame: np.ndarray | None = None
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self.ptz_metrics.autotracker_enabled.value
|
self.camera_config.onvif.autotracking.enabled
|
||||||
or self.detect_config.stationary.classifier
|
or self.detect_config.stationary.classifier
|
||||||
):
|
):
|
||||||
yuv_frame = self.frame_manager.get(
|
yuv_frame = self.frame_manager.get(
|
||||||
@@ -534,7 +534,7 @@ class NorfairTracker(ObjectTracker):
|
|||||||
points = np.array([[obj[2][0], obj[2][1]], [obj[2][2], obj[2][3]]])
|
points = np.array([[obj[2][0], obj[2][1]], [obj[2][2], obj[2][3]]])
|
||||||
|
|
||||||
embedding = None
|
embedding = None
|
||||||
if self.ptz_metrics.autotracker_enabled.value:
|
if self.camera_config.onvif.autotracking.enabled:
|
||||||
embedding = get_histogram(
|
embedding = get_histogram(
|
||||||
yuv_frame, obj[2][0], obj[2][1], obj[2][2], obj[2][3]
|
yuv_frame, obj[2][0], obj[2][1], obj[2][2], obj[2][3]
|
||||||
)
|
)
|
||||||
@@ -559,7 +559,7 @@ class NorfairTracker(ObjectTracker):
|
|||||||
|
|
||||||
coord_transformations = None
|
coord_transformations = None
|
||||||
|
|
||||||
if self.ptz_metrics.autotracker_enabled.value:
|
if self.camera_config.onvif.autotracking.enabled:
|
||||||
# we must have been enabled by mqtt, so set up the estimator
|
# we must have been enabled by mqtt, so set up the estimator
|
||||||
if not self.ptz_motion_estimator:
|
if not self.ptz_motion_estimator:
|
||||||
self.ptz_motion_estimator = PtzMotionEstimator(
|
self.ptz_motion_estimator = PtzMotionEstimator(
|
||||||
|
|||||||
+10
-2
@@ -94,6 +94,7 @@ class CameraTracker(FrigateProcess):
|
|||||||
self.config.detect.fps,
|
self.config.detect.fps,
|
||||||
name=self.config.name,
|
name=self.config.name,
|
||||||
ptz_metrics=self.ptz_metrics,
|
ptz_metrics=self.ptz_metrics,
|
||||||
|
autotracking_enabled=self.config.onvif.autotracking.enabled,
|
||||||
)
|
)
|
||||||
object_detector = RemoteObjectDetector(
|
object_detector = RemoteObjectDetector(
|
||||||
self.config.name,
|
self.config.name,
|
||||||
@@ -195,10 +196,12 @@ def process_frames(
|
|||||||
None,
|
None,
|
||||||
{camera_config.name: camera_config},
|
{camera_config.name: camera_config},
|
||||||
[
|
[
|
||||||
|
CameraConfigUpdateEnum.autotracking,
|
||||||
CameraConfigUpdateEnum.detect,
|
CameraConfigUpdateEnum.detect,
|
||||||
CameraConfigUpdateEnum.enabled,
|
CameraConfigUpdateEnum.enabled,
|
||||||
CameraConfigUpdateEnum.motion,
|
CameraConfigUpdateEnum.motion,
|
||||||
CameraConfigUpdateEnum.objects,
|
CameraConfigUpdateEnum.objects,
|
||||||
|
CameraConfigUpdateEnum.onvif,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -235,6 +238,11 @@ def process_frames(
|
|||||||
motion_detector.config = camera_config.motion
|
motion_detector.config = camera_config.motion
|
||||||
motion_detector.update_mask()
|
motion_detector.update_mask()
|
||||||
|
|
||||||
|
if "autotracking" in updated_configs or "onvif" in updated_configs:
|
||||||
|
motion_detector.autotracking_enabled = (
|
||||||
|
camera_config.onvif.autotracking.enabled
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not camera_enabled
|
not camera_enabled
|
||||||
and prev_enabled != camera_enabled
|
and prev_enabled != camera_enabled
|
||||||
@@ -349,8 +357,8 @@ def process_frames(
|
|||||||
|
|
||||||
# only add in the motion boxes when not calibrating and a ptz is not moving via autotracking
|
# only add in the motion boxes when not calibrating and a ptz is not moving via autotracking
|
||||||
# the ptz timestamps are only maintained while autotracking is on, so gate
|
# the ptz timestamps are only maintained while autotracking is on, so gate
|
||||||
# on the metric rather than trusting them to be reset otherwise
|
# on the config rather than trusting them to be reset otherwise
|
||||||
ptz_moving = ptz_metrics.autotracker_enabled.value and (
|
ptz_moving = camera_config.onvif.autotracking.enabled and (
|
||||||
ptz_moving_at_frame_time(
|
ptz_moving_at_frame_time(
|
||||||
frame_time,
|
frame_time,
|
||||||
ptz_metrics.start_time.value,
|
ptz_metrics.start_time.value,
|
||||||
|
|||||||
Reference in New Issue
Block a user