Basic PTZ object autotracking functionality (#6913)

* Basic functionality

* Threaded motion estimator

* Revert "Threaded motion estimator"

This reverts commit 3171801607.

* Don't detect motion when ptz is moving

* fix motion logic

* fix mypy error

* Add threaded queue for movement for slower ptzs

* Move queues per camera

* Move autotracker start to app.py

* iou value for tracked object

* mqtt callback

* tracked object should be initially motionless

* only draw thicker box if autotracking is enabled

* Init if enabled when initially disabled in config

* Fix init

* Thread names

* Always use motion estimator

* docs

* clarify fov support

* remove size ratio

* use mp event instead of value for ptz status

* update autotrack at half fps

* fix merge conflict

* fix event type for mypy

* clean up

* Clean up

* remove unused code

* merge conflict fix

* docs: update link to object_detectors page

* Update docs/docs/configuration/autotracking.md

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>

* clarify wording

* pass actual instances directly

* default return preset

* fix type

* Error message when onvif init fails

* disable autotracking if onvif init fails

* disable autotracking if onvif init fails

* ptz module

* verify required_zones in config

* update util after dev merge

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
This commit is contained in:
Josh Hawkins
2023-07-08 07:04:47 -05:00
committed by GitHub
parent d6f82f9edc
commit 88fc0fac8f
15 changed files with 770 additions and 17 deletions

View File

@@ -5,7 +5,8 @@ import numpy as np
from norfair import Detection, Drawable, Tracker, draw_boxes
from norfair.drawing.drawer import Drawer
from frigate.config import DetectConfig
from frigate.config import CameraConfig
from frigate.ptz.autotrack import PtzMotionEstimator
from frigate.track import ObjectTracker
from frigate.util.image import intersection_over_union
@@ -54,12 +55,16 @@ def frigate_distance(detection: Detection, tracked_object) -> float:
class NorfairTracker(ObjectTracker):
def __init__(self, config: DetectConfig):
def __init__(self, config: CameraConfig, ptz_autotracker_enabled, ptz_stopped):
self.tracked_objects = {}
self.disappeared = {}
self.positions = {}
self.max_disappeared = config.max_disappeared
self.detect_config = config
self.max_disappeared = config.detect.max_disappeared
self.camera_config = config
self.detect_config = config.detect
self.ptz_autotracker_enabled = ptz_autotracker_enabled.value
self.ptz_stopped = ptz_stopped
self.camera_name = config.name
self.track_id_map = {}
# TODO: could also initialize a tracker per object class if there
# was a good reason to have different distance calculations
@@ -69,6 +74,8 @@ class NorfairTracker(ObjectTracker):
initialization_delay=0,
hit_counter_max=self.max_disappeared,
)
if self.ptz_autotracker_enabled:
self.ptz_motion_estimator = PtzMotionEstimator(config, self.ptz_stopped)
def register(self, track_id, obj):
rand_id = "".join(random.choices(string.ascii_lowercase + string.digits, k=6))
@@ -230,7 +237,16 @@ class NorfairTracker(ObjectTracker):
)
)
tracked_objects = self.tracker.update(detections=norfair_detections)
coord_transformations = None
if self.ptz_autotracker_enabled:
coord_transformations = self.ptz_motion_estimator.motion_estimator(
detections, frame_time, self.camera_name
)
tracked_objects = self.tracker.update(
detections=norfair_detections, coord_transformations=coord_transformations
)
# update or create new tracks
active_ids = []