diff --git a/docs/docs/configuration/index.md b/docs/docs/configuration/index.md index 42c62cf41..52cfefcdd 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