Skip to content

Commit

Permalink
Fix max_frames, improve stationary objects in masked areas (blakeblac…
Browse files Browse the repository at this point in the history
…kshear#6815)

* fix issue with max_frames

* dont consider stationary until the threshold

* require a stationary interval

* try to fix formatter issues
  • Loading branch information
blakeblackshear committed Jun 16, 2023
1 parent 3efa77f commit ca7853c
Show file tree
Hide file tree
Showing 8 changed files with 30 additions and 21 deletions.
8 changes: 6 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,11 @@
"isort.args": ["--settings-path=./pyproject.toml"],
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnSave": true
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.organizeImports": true
}
},
"[json][jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
Expand All @@ -86,7 +90,7 @@
"editor.tabSize": 2
},
"cSpell.ignoreWords": ["rtmp"],
"cSpell.words": ["preact"]
"cSpell.words": ["preact", "astype", "hwaccel", "mqtt"]
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/configuration/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,10 @@ detect:
max_disappeared: 25
# Optional: Configuration for stationary object tracking
stationary:
# Optional: Frequency for confirming stationary objects (default: shown below)
# When set to 0, object detection will not confirm stationary objects until movement is detected.
# Optional: Frequency for confirming stationary objects (default: same as threshold)
# When set to 1, object detection will run to confirm the object still exists on every frame.
# If set to 10, object detection will run to confirm the object still exists on every 10th frame.
interval: 0
interval: 50
# 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)
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/configuration/stationary_objects.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Stationary Objects

An object is considered stationary when it is being tracked and has been in a very similar position for a certain number of frames. This number is defined in the configuration under `detect -> stationary -> threshold`, and is 10x the frame rate (or 10 seconds) by default. Once an object is considered stationary, it will remain stationary until motion occurs near the object at which point object detection will start running again. If the object changes location, it will be considered active.
An object is considered stationary when it is being tracked and has been in a very similar position for a certain number of frames. This number is defined in the configuration under `detect -> stationary -> threshold`, and is 10x the frame rate (or 10 seconds) by default. Once an object is considered stationary, it will remain stationary until motion occurs within the object at which point object detection will start running again. If the object changes location, it will be considered active.

## Why does it matter if an object is stationary?

Expand All @@ -13,11 +13,11 @@ The default config is:
```yaml
detect:
stationary:
interval: 0
interval: 50
threshold: 50
```

`interval` is defined as the frequency for running detection on stationary objects. This means that by default once an object is considered stationary, detection will not be run on it until motion is detected. With `interval > 0`, every nth frames detection will be run to make sure the object is still there.
`interval` is defined as the frequency for running detection on stationary objects. This means that by default once an object is considered stationary, detection will not be run on it until motion is detected or until the interval (every 50th frame by default). With `interval >= 1`, every nth frames detection will be run to make sure the object is still there.

NOTE: There is no way to disable stationary object tracking with this value.

Expand Down
8 changes: 4 additions & 4 deletions frigate/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@

from frigate.const import CACHE_DIR, DEFAULT_DB_PATH, REGEX_CAMERA_NAME, YAML_EXT
from frigate.detectors import DetectorConfig, ModelConfig
from frigate.detectors.detector_config import InputTensorEnum # noqa: F401
from frigate.detectors.detector_config import PixelFormatEnum # noqa: F401
from frigate.detectors.detector_config import BaseDetectorConfig
from frigate.ffmpeg_presets import (
parse_preset_hardware_acceleration_decode,
Expand Down Expand Up @@ -251,9 +249,8 @@ class StationaryMaxFramesConfig(FrigateBaseModel):

class StationaryConfig(FrigateBaseModel):
interval: Optional[int] = Field(
default=0,
title="Frame interval for checking stationary objects.",
ge=0,
gt=0,
)
threshold: Optional[int] = Field(
title="Number of frames without a position change for an object to be considered stationary",
Expand Down Expand Up @@ -963,6 +960,9 @@ def runtime_config(self, plus_api: PlusApi = None) -> FrigateConfig:
stationary_threshold = camera_config.detect.fps * 10
if camera_config.detect.stationary.threshold is None:
camera_config.detect.stationary.threshold = stationary_threshold
# default to the stationary_threshold if not defined
if camera_config.detect.stationary.interval is None:
camera_config.detect.stationary.interval = stationary_threshold

# FFMPEG input substitution
for input in camera_config.ffmpeg.inputs:
Expand Down
2 changes: 1 addition & 1 deletion frigate/object_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import numpy as np
from setproctitle import setproctitle

from frigate.config import InputTensorEnum
from frigate.detectors import create_detector
from frigate.detectors.detector_config import InputTensorEnum
from frigate.util import EventsPerSecond, SharedMemoryFrameManager, listen, load_labels

logger = logging.getLogger(__name__)
Expand Down
3 changes: 2 additions & 1 deletion frigate/test/test_object_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

import frigate.detectors as detectors
import frigate.object_detection
from frigate.config import DetectorConfig, InputTensorEnum, ModelConfig
from frigate.config import DetectorConfig, ModelConfig
from frigate.detectors import DetectorTypeEnum
from frigate.detectors.detector_config import InputTensorEnum


class TestLocalObjectDetector(unittest.TestCase):
Expand Down
11 changes: 7 additions & 4 deletions frigate/track/norfair_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,13 @@ def register(self, track_id, obj):
"ymax": self.detect_config.height,
}

def deregister(self, id):
def deregister(self, id, track_id):
del self.tracked_objects[id]
del self.disappeared[id]
self.tracker.tracked_objects = [
o for o in self.tracker.tracked_objects if o.global_id != track_id
]
del self.track_id_map[track_id]

# tracks the current position of the object based on the last N bounding boxes
# returns False if the object has moved outside its previous position
Expand Down Expand Up @@ -167,7 +171,7 @@ def update(self, track_id, obj):
if self.update_position(id, obj["box"]):
self.tracked_objects[id]["motionless_count"] += 1
if self.is_expired(id):
self.deregister(id)
self.deregister(id, track_id)
return
else:
# register the first position change and then only increment if
Expand Down Expand Up @@ -261,8 +265,7 @@ def match_and_update(self, frame_time, detections):
# clear expired tracks
expired_ids = [k for k in self.track_id_map.keys() if k not in active_ids]
for e_id in expired_ids:
self.deregister(self.track_id_map[e_id])
del self.track_id_map[e_id]
self.deregister(self.track_id_map[e_id], e_id)

def debug_draw(self, frame, frame_time):
active_detections = [
Expand Down
7 changes: 4 additions & 3 deletions frigate/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
import numpy as np
from setproctitle import setproctitle

from frigate.config import CameraConfig, DetectConfig, PixelFormatEnum
from frigate.config import CameraConfig, DetectConfig
from frigate.const import CACHE_DIR
from frigate.detectors.detector_config import PixelFormatEnum
from frigate.log import LogPipe
from frigate.motion import MotionDetector
from frigate.motion.improved_motion import ImprovedMotionDetector
Expand Down Expand Up @@ -769,8 +770,8 @@ def process_frames(
stationary_object_ids = [
obj["id"]
for obj in object_tracker.tracked_objects.values()
# if there hasn't been motion for 10 frames
if obj["motionless_count"] >= 10
# if it has exceeded the stationary threshold
if obj["motionless_count"] >= detect_config.stationary.threshold
# and it isn't due for a periodic check
and (
detect_config.stationary.interval == 0
Expand Down

0 comments on commit ca7853c

Please sign in to comment.