diff --git a/frigate/config.py b/frigate/config.py index ae5e9ee80..be02f4607 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -8,7 +8,6 @@ from typing import Dict, List, Optional, Tuple, Union import matplotlib.pyplot as plt import numpy as np -import yaml from pydantic import BaseModel, Extra, Field, validator, parse_obj_as from pydantic.fields import PrivateAttr @@ -19,12 +18,12 @@ from frigate.const import ( YAML_EXT, ) from frigate.util import ( + BoundingBoxTriggerEnum, create_mask, deep_merge, get_ffmpeg_arg_list, escape_special_characters, load_config_with_no_duplicates, - load_labels, ) from frigate.ffmpeg_presets import ( parse_preset_hardware_acceleration, @@ -33,14 +32,11 @@ from frigate.ffmpeg_presets import ( parse_preset_output_rtmp, ) from frigate.detectors import ( - PixelFormatEnum, - InputTensorEnum, ModelConfig, DetectorConfig, ) from frigate.version import VERSION - logger = logging.getLogger(__name__) # TODO: Identify what the default format to display timestamps is @@ -277,13 +273,6 @@ class RuntimeFilterConfig(FilterConfig): extra = Extra.ignore -class BoundingBoxTriggerEnum(str, Enum): - bottom_center = "bottom-center" - left_center = "left-center" - top_center = "top-center" - right_center = "right-center" - - # this uses the base model because the color is an extra attribute class ZoneConfig(BaseModel): filters: Dict[str, FilterConfig] = Field( diff --git a/frigate/object_processing.py b/frigate/object_processing.py index 49679f9b0..e1c2e077a 100644 --- a/frigate/object_processing.py +++ b/frigate/object_processing.py @@ -136,15 +136,19 @@ class TrackedObject: # check zones current_zones = [] - bottom_center = (obj_data["centroid"][0], obj_data["box"][3]) + # check each zone for name, zone in self.camera_config.zones.items(): # if the zone is not for this object type, skip if len(zone.objects) > 0 and not obj_data["label"] in zone.objects: continue - contour = zone.contour + # check if the object is in the zone - if cv2.pointPolygonTest(contour, bottom_center, False) >= 0: + if zone.bounding_box_trigger.is_in_zone( + obj_data["centroid"], + obj_data["box"], + zone.contour, + ): # if the object passed the filters once, dont apply again if name in self.current_zones or not zone_filtered(self, zone.filters): current_zones.append(name) diff --git a/frigate/util.py b/frigate/util.py index 79fe7932f..29d83178f 100755 --- a/frigate/util.py +++ b/frigate/util.py @@ -5,6 +5,7 @@ import shlex import subprocess as sp import json import re +from enum import Enum import signal import traceback import urllib.parse @@ -972,3 +973,24 @@ class SharedMemoryFrameManager(FrameManager): self.shm_store[name].close() self.shm_store[name].unlink() del self.shm_store[name] + + +class BoundingBoxTriggerEnum(str, Enum): + bottom_center = "bottom-center" + left_center = "left-center" + right_center = "right-center" + top_center = "top-center" + + def is_in_zone(self, centroid, box, contour) -> bool: + """Tests a zone based on the bounding box + trigger and the objects bounding box.""" + if self.value is self.bottom_center: + point = (centroid[0], box[3]) + elif self.value is self.left_center: + point = (box[0], centroid[1]) + elif self.value is self.right_center: + point = (box[2], centroid[1]) + elif self.value is self.top_center: + point = (centroid[0], box[1]) + + return cv2.pointPolygonTest(contour, point, False) >= 0