Handle zones and masks as relative coords

This commit is contained in:
Nicolas Mowen 2024-04-08 16:49:46 -06:00
parent c08a198354
commit dc22c8d3f1
4 changed files with 190 additions and 48 deletions

View File

@ -154,6 +154,11 @@ def config():
for cmd in camera_dict["ffmpeg_cmds"]: for cmd in camera_dict["ffmpeg_cmds"]:
cmd["cmd"] = clean_camera_user_pass(" ".join(cmd["cmd"])) cmd["cmd"] = clean_camera_user_pass(" ".join(cmd["cmd"]))
# ensure that zones are relative
for zone in camera_dict.get("zones", []):
config["plus"] = {"enabled": current_app.plus_api.is_active()} config["plus"] = {"enabled": current_app.plus_api.is_active()}
for detector, detector_config in config["detectors"].items(): for detector, detector_config in config["detectors"].items():

View File

@ -539,16 +539,41 @@ class ZoneConfig(BaseModel):
super().__init__(**config) super().__init__(**config)
self._color = config.get("color", (0, 0, 0)) self._color = config.get("color", (0, 0, 0))
coordinates = config["coordinates"] self._contour = config.get("contour", np.array([]))
def generate_contour(self, frame_shape: tuple[int, int]):
coordinates = self.coordinates
if isinstance(coordinates, list): if isinstance(coordinates, list):
explicit = any(p.split(",")[0] > "1.0" for p in coordinates)
self._contour = np.array( self._contour = np.array(
[[int(p.split(",")[0]), int(p.split(",")[1])] for p in coordinates] [
(
[int(p.split(",")[0]), int(p.split(",")[1])]
if explicit
else [
int(float(p.split(",")[0]) * frame_shape[1]),
int(float(p.split(",")[1]) * frame_shape[0]),
]
)
for p in coordinates
]
) )
elif isinstance(coordinates, str): elif isinstance(coordinates, str):
points = coordinates.split(",") points = coordinates.split(",")
explicit = any(p > "1.0" for p in points)
self._contour = np.array( self._contour = np.array(
[[int(points[i]), int(points[i + 1])] for i in range(0, len(points), 2)] [
(
[int(points[i]), int(points[i + 1])]
if explicit
else [
int(float(points[i]) * frame_shape[1]),
int(float(points[i + 1]) * frame_shape[0]),
]
)
for i in range(0, len(points), 2)
]
) )
else: else:
self._contour = np.array([]) self._contour = np.array([])
@ -1346,6 +1371,11 @@ class FrigateConfig(FrigateBaseModel):
) )
camera_config.motion.enabled_in_config = camera_config.motion.enabled camera_config.motion.enabled_in_config = camera_config.motion.enabled
# generate zone contours
if len(camera_config.zones) > 0:
for zone in camera_config.zones.values():
zone.generate_contour(camera_config.frame_shape)
# Set live view stream if none is set # Set live view stream if none is set
if not camera_config.live.stream_name: if not camera_config.live.stream_name:
camera_config.live.stream_name = name camera_config.live.stream_name = name

View File

@ -64,7 +64,7 @@ class TestConfig(unittest.TestCase):
def test_config_class(self): def test_config_class(self):
frigate_config = FrigateConfig(**self.minimal) frigate_config = FrigateConfig(**self.minimal)
assert self.minimal == frigate_config.dict(exclude_unset=True) assert self.minimal == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert "cpu" in runtime_config.detectors.keys() assert "cpu" in runtime_config.detectors.keys()
@ -157,7 +157,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
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
@ -183,7 +183,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert not runtime_config.cameras["back"].birdseye.enabled assert not runtime_config.cameras["back"].birdseye.enabled
@ -209,7 +209,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].birdseye.enabled assert runtime_config.cameras["back"].birdseye.enabled
@ -234,7 +234,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].birdseye.enabled assert runtime_config.cameras["back"].birdseye.enabled
@ -263,7 +263,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert "cat" in runtime_config.cameras["back"].objects.track assert "cat" in runtime_config.cameras["back"].objects.track
@ -288,7 +288,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert "dog" in runtime_config.cameras["back"].objects.filters assert "dog" in runtime_config.cameras["back"].objects.filters
@ -316,7 +316,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert "dog" in runtime_config.cameras["back"].objects.filters assert "dog" in runtime_config.cameras["back"].objects.filters
@ -345,7 +345,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert "dog" in runtime_config.cameras["back"].objects.filters assert "dog" in runtime_config.cameras["back"].objects.filters
@ -375,7 +375,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
back_camera = runtime_config.cameras["back"] back_camera = runtime_config.cameras["back"]
@ -383,6 +383,55 @@ class TestConfig(unittest.TestCase):
assert len(back_camera.objects.filters["dog"].raw_mask) == 2 assert len(back_camera.objects.filters["dog"].raw_mask) == 2
assert len(back_camera.objects.filters["person"].raw_mask) == 1 assert len(back_camera.objects.filters["person"].raw_mask) == 1
def test_motion_mask_relative_matches_explicit(self):
config = {
"mqtt": {"host": "mqtt"},
"record": {
"events": {"retain": {"default": 20, "objects": {"person": 30}}}
},
"cameras": {
"explicit": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 400,
"width": 800,
"fps": 5,
},
"motion": {
"mask": [
"0,0,200,100,600,300,800,400",
]
},
},
"relative": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 400,
"width": 800,
"fps": 5,
},
"motion": {
"mask": [
"0.0,0.0,0.25,0.25,0.75,0.75,1.0,1.0",
]
},
},
},
}
frigate_config = FrigateConfig(**config).runtime_config()
assert np.array_equal(
frigate_config.cameras["explicit"].motion.mask,
frigate_config.cameras["relative"].motion.mask,
)
def test_default_input_args(self): def test_default_input_args(self):
config = { config = {
"mqtt": {"host": "mqtt"}, "mqtt": {"host": "mqtt"},
@ -406,7 +455,7 @@ class TestConfig(unittest.TestCase):
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert "-rtsp_transport" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"] assert "-rtsp_transport" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
@ -435,7 +484,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert "-re" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"] assert "-re" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
@ -465,7 +514,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert "-re" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"] assert "-re" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
@ -500,7 +549,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert "-re" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"] assert "-re" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
@ -530,7 +579,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert ( assert (
@ -608,7 +657,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert isinstance( assert isinstance(
@ -616,6 +665,41 @@ class TestConfig(unittest.TestCase):
) )
assert runtime_config.cameras["back"].zones["test"].color != (0, 0, 0) assert runtime_config.cameras["back"].zones["test"].color != (0, 0, 0)
def test_zone_relative_matches_explicit(self):
config = {
"mqtt": {"host": "mqtt"},
"record": {
"events": {"retain": {"default": 20, "objects": {"person": 30}}}
},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 400,
"width": 800,
"fps": 5,
},
"zones": {
"explicit": {
"coordinates": "0,0,200,100,600,300,800,400",
},
"relative": {
"coordinates": "0.0,0.0,0.25,0.25,0.75,0.75,1.0,1.0",
},
},
}
},
}
frigate_config = FrigateConfig(**config).runtime_config()
assert np.array_equal(
frigate_config.cameras["back"].zones["explicit"].contour,
frigate_config.cameras["back"].zones["relative"].contour,
)
def test_clips_should_default_to_global_objects(self): def test_clips_should_default_to_global_objects(self):
config = { config = {
"mqtt": {"host": "mqtt"}, "mqtt": {"host": "mqtt"},
@ -640,7 +724,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
back_camera = runtime_config.cameras["back"] back_camera = runtime_config.cameras["back"]
@ -671,7 +755,7 @@ class TestConfig(unittest.TestCase):
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
ffmpeg_cmds = runtime_config.cameras["back"].ffmpeg_cmds ffmpeg_cmds = runtime_config.cameras["back"].ffmpeg_cmds
@ -702,7 +786,7 @@ class TestConfig(unittest.TestCase):
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].detect.max_disappeared == 5 * 5 assert runtime_config.cameras["back"].detect.max_disappeared == 5 * 5
@ -730,7 +814,7 @@ class TestConfig(unittest.TestCase):
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].motion.frame_height == 100 assert runtime_config.cameras["back"].motion.frame_height == 100
@ -758,7 +842,7 @@ class TestConfig(unittest.TestCase):
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert round(runtime_config.cameras["back"].motion.contour_area) == 10 assert round(runtime_config.cameras["back"].motion.contour_area) == 10
@ -787,7 +871,7 @@ class TestConfig(unittest.TestCase):
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.model.merged_labelmap[7] == "truck" assert runtime_config.model.merged_labelmap[7] == "truck"
@ -815,7 +899,7 @@ class TestConfig(unittest.TestCase):
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.model.merged_labelmap[0] == "person" assert runtime_config.model.merged_labelmap[0] == "person"
@ -844,7 +928,7 @@ class TestConfig(unittest.TestCase):
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.model.merged_labelmap[0] == "person" assert runtime_config.model.merged_labelmap[0] == "person"
@ -878,7 +962,7 @@ class TestConfig(unittest.TestCase):
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config(PlusApi()) runtime_config = frigate_config.runtime_config(PlusApi())
assert runtime_config.model.merged_labelmap[0] == "amazon" assert runtime_config.model.merged_labelmap[0] == "amazon"
@ -1012,7 +1096,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].detect.max_disappeared == 1 assert runtime_config.cameras["back"].detect.max_disappeared == 1
@ -1040,7 +1124,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].detect.max_disappeared == 25 assert runtime_config.cameras["back"].detect.max_disappeared == 25
@ -1069,7 +1153,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].detect.max_disappeared == 1 assert runtime_config.cameras["back"].detect.max_disappeared == 1
@ -1102,7 +1186,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].snapshots.enabled assert runtime_config.cameras["back"].snapshots.enabled
@ -1130,7 +1214,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].snapshots.bounding_box assert runtime_config.cameras["back"].snapshots.bounding_box
@ -1163,7 +1247,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].snapshots.bounding_box is False assert runtime_config.cameras["back"].snapshots.bounding_box is False
@ -1193,7 +1277,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].live.quality == 4 assert runtime_config.cameras["back"].live.quality == 4
@ -1220,7 +1304,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].live.quality == 8 assert runtime_config.cameras["back"].live.quality == 8
@ -1251,7 +1335,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].live.quality == 7 assert runtime_config.cameras["back"].live.quality == 7
@ -1280,7 +1364,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].timestamp_style.position == "bl" assert runtime_config.cameras["back"].timestamp_style.position == "bl"
@ -1307,7 +1391,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].timestamp_style.position == "tl" assert runtime_config.cameras["back"].timestamp_style.position == "tl"
@ -1336,7 +1420,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].timestamp_style.position == "bl" assert runtime_config.cameras["back"].timestamp_style.position == "bl"
@ -1365,7 +1449,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].snapshots.retain.default == 1.5 assert runtime_config.cameras["back"].snapshots.retain.default == 1.5
@ -1505,7 +1589,7 @@ class TestConfig(unittest.TestCase):
}, },
} }
frigate_config = FrigateConfig(**config) frigate_config = FrigateConfig(**config)
assert config == frigate_config.dict(exclude_unset=True) assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config() runtime_config = frigate_config.runtime_config()
assert "dog" in runtime_config.cameras["back"].objects.filters assert "dog" in runtime_config.cameras["back"].objects.filters

View File

@ -360,14 +360,17 @@ def yuv_crop_and_resize(frame, region, height=None):
# copy u2 # copy u2
yuv_cropped_frame[ yuv_cropped_frame[
size + uv_channel_y_offset : size + uv_channel_y_offset + uv_crop_height, size + uv_channel_y_offset : size + uv_channel_y_offset + uv_crop_height,
size // 2 + uv_channel_x_offset : size // 2 size // 2
+ uv_channel_x_offset : size // 2
+ uv_channel_x_offset + uv_channel_x_offset
+ uv_crop_width, + uv_crop_width,
] = frame[u2[1] : u2[3], u2[0] : u2[2]] ] = frame[u2[1] : u2[3], u2[0] : u2[2]]
# copy v1 # copy v1
yuv_cropped_frame[ yuv_cropped_frame[
size + size // 4 + uv_channel_y_offset : size size
+ size // 4
+ uv_channel_y_offset : size
+ size // 4 + size // 4
+ uv_channel_y_offset + uv_channel_y_offset
+ uv_crop_height, + uv_crop_height,
@ -376,11 +379,14 @@ def yuv_crop_and_resize(frame, region, height=None):
# copy v2 # copy v2
yuv_cropped_frame[ yuv_cropped_frame[
size + size // 4 + uv_channel_y_offset : size size
+ size // 4
+ uv_channel_y_offset : size
+ size // 4 + size // 4
+ uv_channel_y_offset + uv_channel_y_offset
+ uv_crop_height, + uv_crop_height,
size // 2 + uv_channel_x_offset : size // 2 size // 2
+ uv_channel_x_offset : size // 2
+ uv_channel_x_offset + uv_channel_x_offset
+ uv_crop_width, + uv_crop_width,
] = frame[v2[1] : v2[3], v2[0] : v2[2]] ] = frame[v2[1] : v2[3], v2[0] : v2[2]]
@ -727,9 +733,26 @@ def create_mask(frame_shape, mask):
return mask_img return mask_img
def add_mask(mask, mask_img): def add_mask(mask: str, mask_img: np.ndarray):
points = mask.split(",") points = mask.split(",")
# masks and zones are saved as relative coordinates
# we know if any points are > 1 then it is using the
# old native resolution coordinates
explicit = any(x > "1.0" for x in points)
contour = np.array( contour = np.array(
[[int(points[i]), int(points[i + 1])] for i in range(0, len(points), 2)] [
(
[int(points[i]), int(points[i + 1])]
if explicit
else [
int(float(points[i]) * mask_img.shape[1]),
int(float(points[i + 1]) * mask_img.shape[0]),
]
) )
for i in range(0, len(points), 2)
]
)
logger.error(f"the mask is {contour} from {mask} and explicit {explicit}")
cv2.fillPoly(mask_img, pts=[contour], color=(0)) cv2.fillPoly(mask_img, pts=[contour], color=(0))