mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Fix max_frames, improve stationary objects in masked areas (#6815)
* fix issue with max_frames * dont consider stationary until the threshold * require a stationary interval * try to fix formatter issues
This commit is contained in:
parent
3efa77f302
commit
ca7853c087
@ -73,7 +73,11 @@
|
|||||||
"isort.args": ["--settings-path=./pyproject.toml"],
|
"isort.args": ["--settings-path=./pyproject.toml"],
|
||||||
"[python]": {
|
"[python]": {
|
||||||
"editor.defaultFormatter": "ms-python.black-formatter",
|
"editor.defaultFormatter": "ms-python.black-formatter",
|
||||||
"editor.formatOnSave": true
|
"editor.formatOnSave": true,
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll": true,
|
||||||
|
"source.organizeImports": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"[json][jsonc]": {
|
"[json][jsonc]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
@ -86,7 +90,7 @@
|
|||||||
"editor.tabSize": 2
|
"editor.tabSize": 2
|
||||||
},
|
},
|
||||||
"cSpell.ignoreWords": ["rtmp"],
|
"cSpell.ignoreWords": ["rtmp"],
|
||||||
"cSpell.words": ["preact"]
|
"cSpell.words": ["preact", "astype", "hwaccel", "mqtt"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,10 +206,10 @@ detect:
|
|||||||
max_disappeared: 25
|
max_disappeared: 25
|
||||||
# Optional: Configuration for stationary object tracking
|
# Optional: Configuration for stationary object tracking
|
||||||
stationary:
|
stationary:
|
||||||
# Optional: Frequency for confirming stationary objects (default: shown below)
|
# Optional: Frequency for confirming stationary objects (default: same as threshold)
|
||||||
# When set to 0, object detection will not confirm stationary objects until movement is detected.
|
# 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.
|
# 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)
|
# Optional: Number of frames without a position change for an object to be considered stationary (default: 10x the frame rate or 10s)
|
||||||
threshold: 50
|
threshold: 50
|
||||||
# Optional: Define a maximum number of frames for tracking a stationary object (default: not set, track forever)
|
# Optional: Define a maximum number of frames for tracking a stationary object (default: not set, track forever)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Stationary Objects
|
# 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?
|
## Why does it matter if an object is stationary?
|
||||||
|
|
||||||
@ -13,11 +13,11 @@ The default config is:
|
|||||||
```yaml
|
```yaml
|
||||||
detect:
|
detect:
|
||||||
stationary:
|
stationary:
|
||||||
interval: 0
|
interval: 50
|
||||||
threshold: 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.
|
NOTE: There is no way to disable stationary object tracking with this value.
|
||||||
|
|
||||||
|
@ -13,8 +13,6 @@ from pydantic.fields import PrivateAttr
|
|||||||
|
|
||||||
from frigate.const import CACHE_DIR, DEFAULT_DB_PATH, REGEX_CAMERA_NAME, YAML_EXT
|
from frigate.const import CACHE_DIR, DEFAULT_DB_PATH, REGEX_CAMERA_NAME, YAML_EXT
|
||||||
from frigate.detectors import DetectorConfig, ModelConfig
|
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.detectors.detector_config import BaseDetectorConfig
|
||||||
from frigate.ffmpeg_presets import (
|
from frigate.ffmpeg_presets import (
|
||||||
parse_preset_hardware_acceleration_decode,
|
parse_preset_hardware_acceleration_decode,
|
||||||
@ -251,9 +249,8 @@ class StationaryMaxFramesConfig(FrigateBaseModel):
|
|||||||
|
|
||||||
class StationaryConfig(FrigateBaseModel):
|
class StationaryConfig(FrigateBaseModel):
|
||||||
interval: Optional[int] = Field(
|
interval: Optional[int] = Field(
|
||||||
default=0,
|
|
||||||
title="Frame interval for checking stationary objects.",
|
title="Frame interval for checking stationary objects.",
|
||||||
ge=0,
|
gt=0,
|
||||||
)
|
)
|
||||||
threshold: Optional[int] = Field(
|
threshold: Optional[int] = Field(
|
||||||
title="Number of frames without a position change for an object to be considered stationary",
|
title="Number of frames without a position change for an object to be considered stationary",
|
||||||
@ -963,6 +960,9 @@ class FrigateConfig(FrigateBaseModel):
|
|||||||
stationary_threshold = camera_config.detect.fps * 10
|
stationary_threshold = camera_config.detect.fps * 10
|
||||||
if camera_config.detect.stationary.threshold is None:
|
if camera_config.detect.stationary.threshold is None:
|
||||||
camera_config.detect.stationary.threshold = stationary_threshold
|
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
|
# FFMPEG input substitution
|
||||||
for input in camera_config.ffmpeg.inputs:
|
for input in camera_config.ffmpeg.inputs:
|
||||||
|
@ -10,8 +10,8 @@ from abc import ABC, abstractmethod
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from setproctitle import setproctitle
|
from setproctitle import setproctitle
|
||||||
|
|
||||||
from frigate.config import InputTensorEnum
|
|
||||||
from frigate.detectors import create_detector
|
from frigate.detectors import create_detector
|
||||||
|
from frigate.detectors.detector_config import InputTensorEnum
|
||||||
from frigate.util import EventsPerSecond, SharedMemoryFrameManager, listen, load_labels
|
from frigate.util import EventsPerSecond, SharedMemoryFrameManager, listen, load_labels
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -6,8 +6,9 @@ from pydantic import parse_obj_as
|
|||||||
|
|
||||||
import frigate.detectors as detectors
|
import frigate.detectors as detectors
|
||||||
import frigate.object_detection
|
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 import DetectorTypeEnum
|
||||||
|
from frigate.detectors.detector_config import InputTensorEnum
|
||||||
|
|
||||||
|
|
||||||
class TestLocalObjectDetector(unittest.TestCase):
|
class TestLocalObjectDetector(unittest.TestCase):
|
||||||
|
@ -91,9 +91,13 @@ class NorfairTracker(ObjectTracker):
|
|||||||
"ymax": self.detect_config.height,
|
"ymax": self.detect_config.height,
|
||||||
}
|
}
|
||||||
|
|
||||||
def deregister(self, id):
|
def deregister(self, id, track_id):
|
||||||
del self.tracked_objects[id]
|
del self.tracked_objects[id]
|
||||||
del self.disappeared[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
|
# 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
|
# returns False if the object has moved outside its previous position
|
||||||
@ -167,7 +171,7 @@ class NorfairTracker(ObjectTracker):
|
|||||||
if self.update_position(id, obj["box"]):
|
if self.update_position(id, obj["box"]):
|
||||||
self.tracked_objects[id]["motionless_count"] += 1
|
self.tracked_objects[id]["motionless_count"] += 1
|
||||||
if self.is_expired(id):
|
if self.is_expired(id):
|
||||||
self.deregister(id)
|
self.deregister(id, track_id)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
# register the first position change and then only increment if
|
# register the first position change and then only increment if
|
||||||
@ -261,8 +265,7 @@ class NorfairTracker(ObjectTracker):
|
|||||||
# clear expired tracks
|
# clear expired tracks
|
||||||
expired_ids = [k for k in self.track_id_map.keys() if k not in active_ids]
|
expired_ids = [k for k in self.track_id_map.keys() if k not in active_ids]
|
||||||
for e_id in expired_ids:
|
for e_id in expired_ids:
|
||||||
self.deregister(self.track_id_map[e_id])
|
self.deregister(self.track_id_map[e_id], e_id)
|
||||||
del self.track_id_map[e_id]
|
|
||||||
|
|
||||||
def debug_draw(self, frame, frame_time):
|
def debug_draw(self, frame, frame_time):
|
||||||
active_detections = [
|
active_detections = [
|
||||||
|
@ -14,8 +14,9 @@ import cv2
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from setproctitle import setproctitle
|
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.const import CACHE_DIR
|
||||||
|
from frigate.detectors.detector_config import PixelFormatEnum
|
||||||
from frigate.log import LogPipe
|
from frigate.log import LogPipe
|
||||||
from frigate.motion import MotionDetector
|
from frigate.motion import MotionDetector
|
||||||
from frigate.motion.improved_motion import ImprovedMotionDetector
|
from frigate.motion.improved_motion import ImprovedMotionDetector
|
||||||
@ -769,8 +770,8 @@ def process_frames(
|
|||||||
stationary_object_ids = [
|
stationary_object_ids = [
|
||||||
obj["id"]
|
obj["id"]
|
||||||
for obj in object_tracker.tracked_objects.values()
|
for obj in object_tracker.tracked_objects.values()
|
||||||
# if there hasn't been motion for 10 frames
|
# if it has exceeded the stationary threshold
|
||||||
if obj["motionless_count"] >= 10
|
if obj["motionless_count"] >= detect_config.stationary.threshold
|
||||||
# and it isn't due for a periodic check
|
# and it isn't due for a periodic check
|
||||||
and (
|
and (
|
||||||
detect_config.stationary.interval == 0
|
detect_config.stationary.interval == 0
|
||||||
|
Loading…
Reference in New Issue
Block a user