mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-06-13 01:16:53 +02:00
Allow birdseye to be overridden at the camera level (#3083)
* Add camera level processing for birdseye * Add camera level birdseye configruation * Propogate birdseye from global * Update docs to show that birdseye is overridable * Fix incorrect default factory * Update note to indicate values that can be overridden * Cleanup config accessing * Add tests for birdseye config behavior * Fix mistake on test format * Update tests
This commit is contained in:
parent
164e9b7eb8
commit
d749cf2e6b
@ -110,6 +110,7 @@ environment_vars:
|
|||||||
EXAMPLE_VAR: value
|
EXAMPLE_VAR: value
|
||||||
|
|
||||||
# Optional: birdseye configuration
|
# Optional: birdseye configuration
|
||||||
|
# NOTE: Can (enabled, mode) be overridden at the camera level
|
||||||
birdseye:
|
birdseye:
|
||||||
# Optional: Enable birdseye view (default: shown below)
|
# Optional: Enable birdseye view (default: shown below)
|
||||||
enabled: True
|
enabled: True
|
||||||
|
@ -324,6 +324,13 @@ class BirdseyeConfig(FrigateBaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BirdseyeCameraConfig(FrigateBaseModel):
|
||||||
|
enabled: bool = Field(default=True, title="Enable birdseye view for camera.")
|
||||||
|
mode: BirdseyeModeEnum = Field(
|
||||||
|
default=BirdseyeModeEnum.objects, title="Tracking mode for camera."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
FFMPEG_GLOBAL_ARGS_DEFAULT = ["-hide_banner", "-loglevel", "warning"]
|
FFMPEG_GLOBAL_ARGS_DEFAULT = ["-hide_banner", "-loglevel", "warning"]
|
||||||
FFMPEG_INPUT_ARGS_DEFAULT = [
|
FFMPEG_INPUT_ARGS_DEFAULT = [
|
||||||
"-avoid_negative_ts",
|
"-avoid_negative_ts",
|
||||||
@ -539,6 +546,9 @@ class CameraConfig(FrigateBaseModel):
|
|||||||
detect: DetectConfig = Field(
|
detect: DetectConfig = Field(
|
||||||
default_factory=DetectConfig, title="Object detection configuration."
|
default_factory=DetectConfig, title="Object detection configuration."
|
||||||
)
|
)
|
||||||
|
birdseye: BirdseyeCameraConfig = Field(
|
||||||
|
default_factory=BirdseyeCameraConfig, title="Birdseye camera configuration."
|
||||||
|
)
|
||||||
timestamp_style: TimestampStyleConfig = Field(
|
timestamp_style: TimestampStyleConfig = Field(
|
||||||
default_factory=TimestampStyleConfig, title="Timestamp style configuration."
|
default_factory=TimestampStyleConfig, title="Timestamp style configuration."
|
||||||
)
|
)
|
||||||
@ -775,6 +785,7 @@ class FrigateConfig(FrigateBaseModel):
|
|||||||
# Global config to propegate down to camera level
|
# Global config to propegate down to camera level
|
||||||
global_config = config.dict(
|
global_config = config.dict(
|
||||||
include={
|
include={
|
||||||
|
"birdseye": ...,
|
||||||
"record": ...,
|
"record": ...,
|
||||||
"snapshots": ...,
|
"snapshots": ...,
|
||||||
"live": ...,
|
"live": ...,
|
||||||
|
@ -190,14 +190,14 @@ class BirdsEyeFrameManager:
|
|||||||
channel_dims,
|
channel_dims,
|
||||||
)
|
)
|
||||||
|
|
||||||
def camera_active(self, object_box_count, motion_box_count):
|
def camera_active(self, mode, object_box_count, motion_box_count):
|
||||||
if self.mode == BirdseyeModeEnum.continuous:
|
if mode == BirdseyeModeEnum.continuous:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self.mode == BirdseyeModeEnum.motion and motion_box_count > 0:
|
if mode == BirdseyeModeEnum.motion and motion_box_count > 0:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self.mode == BirdseyeModeEnum.objects and object_box_count > 0:
|
if mode == BirdseyeModeEnum.objects and object_box_count > 0:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_frame(self):
|
def update_frame(self):
|
||||||
@ -311,10 +311,14 @@ class BirdsEyeFrameManager:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def update(self, camera, object_count, motion_count, frame_time, frame) -> bool:
|
def update(self, camera, object_count, motion_count, frame_time, frame) -> bool:
|
||||||
|
# don't process if birdseye is disabled for this camera
|
||||||
|
camera_config = self.config.cameras[camera].birdseye
|
||||||
|
if not camera_config.enabled:
|
||||||
|
return False
|
||||||
|
|
||||||
# update the last active frame for the camera
|
# update the last active frame for the camera
|
||||||
self.cameras[camera]["current_frame"] = frame_time
|
self.cameras[camera]["current_frame"] = frame_time
|
||||||
if self.camera_active(object_count, motion_count):
|
if self.camera_active(camera_config.mode, object_count, motion_count):
|
||||||
self.cameras[camera]["last_active_frame"] = frame_time
|
self.cameras[camera]["last_active_frame"] = frame_time
|
||||||
|
|
||||||
now = datetime.datetime.now().timestamp()
|
now = datetime.datetime.now().timestamp()
|
||||||
|
@ -2,6 +2,7 @@ import unittest
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
from frigate.config import (
|
from frigate.config import (
|
||||||
|
BirdseyeModeEnum,
|
||||||
FrigateConfig,
|
FrigateConfig,
|
||||||
DetectorTypeEnum,
|
DetectorTypeEnum,
|
||||||
)
|
)
|
||||||
@ -80,6 +81,62 @@ class TestConfig(unittest.TestCase):
|
|||||||
runtime_config = frigate_config.runtime_config
|
runtime_config = frigate_config.runtime_config
|
||||||
assert "dog" in runtime_config.cameras["back"].objects.track
|
assert "dog" in runtime_config.cameras["back"].objects.track
|
||||||
|
|
||||||
|
def test_override_birdseye(self):
|
||||||
|
config = {
|
||||||
|
"mqtt": {"host": "mqtt"},
|
||||||
|
"birdseye": { "enabled": True, "mode": "continuous" },
|
||||||
|
"cameras": {
|
||||||
|
"back": {
|
||||||
|
"ffmpeg": {
|
||||||
|
"inputs": [
|
||||||
|
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"detect": {
|
||||||
|
"height": 1080,
|
||||||
|
"width": 1920,
|
||||||
|
"fps": 5,
|
||||||
|
},
|
||||||
|
"birdseye": {
|
||||||
|
"enabled": False,
|
||||||
|
"mode": "motion"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
frigate_config = FrigateConfig(**config)
|
||||||
|
assert config == frigate_config.dict(exclude_unset=True)
|
||||||
|
|
||||||
|
runtime_config = frigate_config.runtime_config
|
||||||
|
assert not runtime_config.cameras["back"].birdseye.enabled
|
||||||
|
assert runtime_config.cameras["back"].birdseye.mode is BirdseyeModeEnum.motion
|
||||||
|
|
||||||
|
def test_inherit_birdseye(self):
|
||||||
|
config = {
|
||||||
|
"mqtt": {"host": "mqtt"},
|
||||||
|
"birdseye": { "enabled": True, "mode": "continuous" },
|
||||||
|
"cameras": {
|
||||||
|
"back": {
|
||||||
|
"ffmpeg": {
|
||||||
|
"inputs": [
|
||||||
|
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"detect": {
|
||||||
|
"height": 1080,
|
||||||
|
"width": 1920,
|
||||||
|
"fps": 5,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
frigate_config = FrigateConfig(**config)
|
||||||
|
assert config == frigate_config.dict(exclude_unset=True)
|
||||||
|
|
||||||
|
runtime_config = frigate_config.runtime_config
|
||||||
|
assert runtime_config.cameras["back"].birdseye.enabled
|
||||||
|
assert runtime_config.cameras["back"].birdseye.mode is BirdseyeModeEnum.continuous
|
||||||
|
|
||||||
def test_override_tracked_objects(self):
|
def test_override_tracked_objects(self):
|
||||||
config = {
|
config = {
|
||||||
"mqtt": {"host": "mqtt"},
|
"mqtt": {"host": "mqtt"},
|
||||||
|
Loading…
Reference in New Issue
Block a user