From 304ffa86e83ff2b9ccac4386f3db730c230589ab Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Sun, 13 Feb 2022 08:58:44 -0600 Subject: [PATCH 1/3] refactor stationary config into section --- docs/docs/configuration/index.md | 21 +++++++++++++----- frigate/config.py | 38 +++++++++++++++++++++++--------- frigate/object_processing.py | 4 ++-- frigate/objects.py | 2 +- frigate/video.py | 4 ++-- 5 files changed, 49 insertions(+), 20 deletions(-) diff --git a/docs/docs/configuration/index.md b/docs/docs/configuration/index.md index a929d8363..beb98175b 100644 --- a/docs/docs/configuration/index.md +++ b/docs/docs/configuration/index.md @@ -159,11 +159,22 @@ detect: enabled: True # Optional: Number of frames without a detection before frigate considers an object to be gone. (default: 5x the frame rate) max_disappeared: 25 - # Optional: Frequency for running detection on stationary objects (default: shown below) - # When set to 0, object detection will never be run on stationary objects. If set to 10, it will be run on every 10th frame. - stationary_interval: 0 - # Optional: Number of frames without a position change for an object to be considered stationary (default: 10x the frame rate or 10s) - stationary_threshold: 50 + stationary: + # Optional: Frequency for running detection on stationary objects (default: shown below) + # When set to 0, object detection will never be run on stationary objects. If set to 10, it will be run on every 10th frame. + interval: 0 + # Optional: Number of frames without a position change for an object to be considered stationary (default: 10x the frame rate or 10s) + threshold: 50 + # Optional: Define a maximum number of frames for tracking a stationary object (default: not set, track forever) + # This can help with false positives for objects that should only be stationary for a limited amount of time. + # It can also be used to disable stationary object tracking. For example, you may want to set a value for person, but leave + # car at the default. + max_frames: + # Optional: Default for all object types (default: not set, track forever) + default: 3000 + # Optional: Object specific values + objects: + person: 1000 # Optional: Object configuration # NOTE: Can be overridden at the camera level diff --git a/frigate/config.py b/frigate/config.py index 3bfda8c55..c210713a2 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -162,6 +162,29 @@ class RuntimeMotionConfig(MotionConfig): extra = Extra.ignore +class StationaryMaxFramesConfig(FrigateBaseModel): + default: Optional[int] = Field(title="Default max frames.", ge=1) + objects: Dict[str, int] = Field( + default_factory=dict, title="Object specific max frames." + ) + + +class StationaryConfig(FrigateBaseModel): + interval: Optional[int] = Field( + default=0, + title="Frame interval for checking stationary objects.", + ge=0, + ) + threshold: Optional[int] = Field( + title="Number of frames without a position change for an object to be considered stationary", + ge=1, + ) + max_frames: StationaryMaxFramesConfig = Field( + default_factory=StationaryMaxFramesConfig, + title="Max frames for stationary objects.", + ) + + class DetectConfig(FrigateBaseModel): height: int = Field(default=720, title="Height of the stream for the detect role.") width: int = Field(default=1280, title="Width of the stream for the detect role.") @@ -172,14 +195,9 @@ class DetectConfig(FrigateBaseModel): max_disappeared: Optional[int] = Field( title="Maximum number of frames the object can dissapear before detection ends." ) - stationary_interval: Optional[int] = Field( - default=0, - title="Frame interval for checking stationary objects.", - ge=0, - ) - stationary_threshold: Optional[int] = Field( - title="Number of frames without a position change for an object to be considered stationary", - ge=1, + stationary: StationaryConfig = Field( + default_factory=StationaryConfig, + title="Stationary objects config.", ) @@ -772,8 +790,8 @@ class FrigateConfig(FrigateBaseModel): # Default stationary_threshold configuration stationary_threshold = camera_config.detect.fps * 10 - if camera_config.detect.stationary_threshold is None: - camera_config.detect.stationary_threshold = stationary_threshold + if camera_config.detect.stationary.threshold is None: + camera_config.detect.stationary.threshold = stationary_threshold # FFMPEG input substitution for input in camera_config.ffmpeg.inputs: diff --git a/frigate/object_processing.py b/frigate/object_processing.py index 527e080b3..37d45e127 100644 --- a/frigate/object_processing.py +++ b/frigate/object_processing.py @@ -161,7 +161,7 @@ class TrackedObject: # if the motionless_count reaches the stationary threshold if ( self.obj_data["motionless_count"] - == self.camera_config.detect.stationary_threshold + == self.camera_config.detect.stationary.threshold ): significant_change = True @@ -194,7 +194,7 @@ class TrackedObject: "area": self.obj_data["area"], "region": self.obj_data["region"], "stationary": self.obj_data["motionless_count"] - > self.camera_config.detect.stationary_threshold, + > self.camera_config.detect.stationary.threshold, "motionless_count": self.obj_data["motionless_count"], "position_changes": self.obj_data["position_changes"], "current_zones": self.current_zones.copy(), diff --git a/frigate/objects.py b/frigate/objects.py index 7adf421d9..874fc9d75 100644 --- a/frigate/objects.py +++ b/frigate/objects.py @@ -104,7 +104,7 @@ class ObjectTracker: if ( self.tracked_objects[id]["position_changes"] == 0 or self.tracked_objects[id]["motionless_count"] - >= self.detect_config.stationary_threshold + >= self.detect_config.stationary.threshold ): self.tracked_objects[id]["position_changes"] += 1 self.tracked_objects[id]["motionless_count"] = 0 diff --git a/frigate/video.py b/frigate/video.py index cb201fd22..26b99176f 100755 --- a/frigate/video.py +++ b/frigate/video.py @@ -511,8 +511,8 @@ def process_frames( if obj["motionless_count"] >= 10 # and it isn't due for a periodic check and ( - detect_config.stationary_interval == 0 - or obj["motionless_count"] % detect_config.stationary_interval != 0 + detect_config.stationary.interval == 0 + or obj["motionless_count"] % detect_config.stationary.interval != 0 ) # and it hasn't disappeared and object_tracker.disappeared[obj["id"]] == 0 From 3be0b915adce887195141f964ed4796ba652805b Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Sun, 13 Feb 2022 10:20:38 -0600 Subject: [PATCH 2/3] deregister based on max_frames setting --- frigate/objects.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/frigate/objects.py b/frigate/objects.py index 874fc9d75..7b66536c2 100644 --- a/frigate/objects.py +++ b/frigate/objects.py @@ -93,11 +93,33 @@ class ObjectTracker: return True + def is_expired(self, id): + obj = self.tracked_objects[id] + # get the max frames for this label type or the default + max_frames = self.detect_config.stationary.max_frames.objects.get( + obj["label"], self.detect_config.stationary.max_frames.default + ) + + # if there is no max_frames for this label type, continue + if max_frames is None: + return False + + # if the object has exceeded the max_frames setting, deregister + if ( + obj["motionless_count"] - self.detect_config.stationary.threshold + > max_frames + ): + print(f"expired: {obj['motionless_count']}") + return True + def update(self, id, new_obj): self.disappeared[id] = 0 # update the motionless count if the object has not moved to a new position if self.update_position(id, new_obj["box"]): self.tracked_objects[id]["motionless_count"] += 1 + if self.is_expired(id): + self.deregister(id) + return else: # register the first position change and then only increment if # the object was previously stationary @@ -112,9 +134,11 @@ class ObjectTracker: self.tracked_objects[id].update(new_obj) def update_frame_times(self, frame_time): - for id in self.tracked_objects.keys(): + for id in list(self.tracked_objects.keys()): self.tracked_objects[id]["frame_time"] = frame_time self.tracked_objects[id]["motionless_count"] += 1 + if self.is_expired(id): + self.deregister(id) def match_and_update(self, frame_time, new_objects): # group by name From e5714f5fbc35e226399247f6ef6a26d79cd53c97 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Sun, 13 Feb 2022 10:27:58 -0600 Subject: [PATCH 3/3] add missing optional comment in docs --- docs/docs/configuration/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/configuration/index.md b/docs/docs/configuration/index.md index beb98175b..e334d88ee 100644 --- a/docs/docs/configuration/index.md +++ b/docs/docs/configuration/index.md @@ -159,6 +159,7 @@ detect: enabled: True # Optional: Number of frames without a detection before frigate considers an object to be gone. (default: 5x the frame rate) max_disappeared: 25 + # Optional: Configuration for stationary object tracking stationary: # Optional: Frequency for running detection on stationary objects (default: shown below) # When set to 0, object detection will never be run on stationary objects. If set to 10, it will be run on every 10th frame.