|
46 | 46 | get_ffmpeg_arg_list,
|
47 | 47 | load_config_with_no_duplicates,
|
48 | 48 | )
|
| 49 | +from frigate.util.config import get_relative_coordinates |
49 | 50 | from frigate.util.image import create_mask
|
50 | 51 | from frigate.util.services import auto_detect_hwaccel, get_video_properties
|
51 | 52 |
|
@@ -348,35 +349,7 @@ class RuntimeMotionConfig(MotionConfig):
|
348 | 349 | def __init__(self, **config):
|
349 | 350 | frame_shape = config.get("frame_shape", (1, 1))
|
350 | 351 |
|
351 |
| - mask = config.get("mask", "") |
352 |
| - |
353 |
| - # masks and zones are saved as relative coordinates |
354 |
| - # we know if any points are > 1 then it is using the |
355 |
| - # old native resolution coordinates |
356 |
| - if mask: |
357 |
| - if isinstance(mask, list) and any(x > "1.0" for x in mask[0].split(",")): |
358 |
| - relative_masks = [] |
359 |
| - for m in mask: |
360 |
| - points = m.split(",") |
361 |
| - relative_masks.append( |
362 |
| - ",".join( |
363 |
| - [ |
364 |
| - f"{round(int(points[i]) / frame_shape[1], 3)},{round(int(points[i + 1]) / frame_shape[0], 3)}" |
365 |
| - for i in range(0, len(points), 2) |
366 |
| - ] |
367 |
| - ) |
368 |
| - ) |
369 |
| - |
370 |
| - mask = relative_masks |
371 |
| - elif isinstance(mask, str) and any(x > "1.0" for x in mask.split(",")): |
372 |
| - points = mask.split(",") |
373 |
| - mask = ",".join( |
374 |
| - [ |
375 |
| - f"{round(int(points[i]) / frame_shape[1], 3)},{round(int(points[i + 1]) / frame_shape[0], 3)}" |
376 |
| - for i in range(0, len(points), 2) |
377 |
| - ] |
378 |
| - ) |
379 |
| - |
| 352 | + mask = get_relative_coordinates(config.get("mask", ""), frame_shape) |
380 | 353 | config["raw_mask"] = mask
|
381 | 354 |
|
382 | 355 | if mask:
|
@@ -508,34 +481,7 @@ class RuntimeFilterConfig(FilterConfig):
|
508 | 481 |
|
509 | 482 | def __init__(self, **config):
|
510 | 483 | frame_shape = config.get("frame_shape", (1, 1))
|
511 |
| - mask = config.get("mask") |
512 |
| - |
513 |
| - # masks and zones are saved as relative coordinates |
514 |
| - # we know if any points are > 1 then it is using the |
515 |
| - # old native resolution coordinates |
516 |
| - if mask: |
517 |
| - if isinstance(mask, list) and any(x > "1.0" for x in mask[0].split(",")): |
518 |
| - relative_masks = [] |
519 |
| - for m in mask: |
520 |
| - points = m.split(",") |
521 |
| - relative_masks.append( |
522 |
| - ",".join( |
523 |
| - [ |
524 |
| - f"{round(int(points[i]) / frame_shape[1], 3)},{round(int(points[i + 1]) / frame_shape[0], 3)}" |
525 |
| - for i in range(0, len(points), 2) |
526 |
| - ] |
527 |
| - ) |
528 |
| - ) |
529 |
| - |
530 |
| - mask = relative_masks |
531 |
| - elif isinstance(mask, str) and any(x > "1.0" for x in mask.split(",")): |
532 |
| - points = mask.split(",") |
533 |
| - mask = ",".join( |
534 |
| - [ |
535 |
| - f"{round(int(points[i]) / frame_shape[1], 3)},{round(int(points[i + 1]) / frame_shape[0], 3)}" |
536 |
| - for i in range(0, len(points), 2) |
537 |
| - ] |
538 |
| - ) |
| 484 | + mask = get_relative_coordinates(config.get("mask"), frame_shape) |
539 | 485 |
|
540 | 486 | config["raw_mask"] = mask
|
541 | 487 |
|
@@ -1231,6 +1177,20 @@ def verify_zone_objects_are_tracked(camera_config: CameraConfig) -> None:
|
1231 | 1177 | )
|
1232 | 1178 |
|
1233 | 1179 |
|
| 1180 | +def verify_required_zones_exist(camera_config: CameraConfig) -> None: |
| 1181 | + for det_zone in camera_config.review.detections.required_zones: |
| 1182 | + if det_zone not in camera_config.zones.keys(): |
| 1183 | + raise ValueError( |
| 1184 | + f"Camera {camera_config.name} has a required zone for detections {det_zone} that is not defined." |
| 1185 | + ) |
| 1186 | + |
| 1187 | + for det_zone in camera_config.review.alerts.required_zones: |
| 1188 | + if det_zone not in camera_config.zones.keys(): |
| 1189 | + raise ValueError( |
| 1190 | + f"Camera {camera_config.name} has a required zone for alerts {det_zone} that is not defined." |
| 1191 | + ) |
| 1192 | + |
| 1193 | + |
1234 | 1194 | def verify_autotrack_zones(camera_config: CameraConfig) -> ValueError | None:
|
1235 | 1195 | """Verify that required_zones are specified when autotracking is enabled."""
|
1236 | 1196 | if (
|
@@ -1456,9 +1416,15 @@ def runtime_config(self, plus_api: PlusApi = None) -> FrigateConfig:
|
1456 | 1416 | else [filter.mask]
|
1457 | 1417 | )
|
1458 | 1418 | object_mask = (
|
1459 |
| - camera_config.objects.mask |
1460 |
| - if isinstance(camera_config.objects.mask, list) |
1461 |
| - else [camera_config.objects.mask] |
| 1419 | + get_relative_coordinates( |
| 1420 | + ( |
| 1421 | + camera_config.objects.mask |
| 1422 | + if isinstance(camera_config.objects.mask, list) |
| 1423 | + else [camera_config.objects.mask] |
| 1424 | + ), |
| 1425 | + camera_config.frame_shape, |
| 1426 | + ) |
| 1427 | + or [] |
1462 | 1428 | )
|
1463 | 1429 | filter.mask = filter_mask + object_mask
|
1464 | 1430 |
|
@@ -1495,6 +1461,7 @@ def runtime_config(self, plus_api: PlusApi = None) -> FrigateConfig:
|
1495 | 1461 | verify_recording_retention(camera_config)
|
1496 | 1462 | verify_recording_segments_setup_with_reasonable_time(camera_config)
|
1497 | 1463 | verify_zone_objects_are_tracked(camera_config)
|
| 1464 | + verify_required_zones_exist(camera_config) |
1498 | 1465 | verify_autotrack_zones(camera_config)
|
1499 | 1466 | verify_motion_and_detect(camera_config)
|
1500 | 1467 |
|
|
0 commit comments