mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-05 18:55:23 +03:00
small tweaks and a bugfix
This commit is contained in:
parent
50f113277b
commit
a67ec5a97c
@ -144,6 +144,7 @@ class PtzAutoTracker:
|
|||||||
self.ptz_metrics = ptz_metrics
|
self.ptz_metrics = ptz_metrics
|
||||||
self.tracked_object: dict[str, object] = {}
|
self.tracked_object: dict[str, object] = {}
|
||||||
self.tracked_object_previous: dict[str, object] = {}
|
self.tracked_object_previous: dict[str, object] = {}
|
||||||
|
self.previous_frame_time = None
|
||||||
self.object_types = {}
|
self.object_types = {}
|
||||||
self.required_zones = {}
|
self.required_zones = {}
|
||||||
self.move_queues = {}
|
self.move_queues = {}
|
||||||
@ -204,34 +205,67 @@ class PtzAutoTracker:
|
|||||||
tilt = 0
|
tilt = 0
|
||||||
|
|
||||||
while not self.move_queues[camera].empty():
|
while not self.move_queues[camera].empty():
|
||||||
queued_pan, queued_tilt = self.move_queues[camera].queue[0]
|
frame_time, queued_pan, queued_tilt = self.move_queues[
|
||||||
|
camera
|
||||||
|
].queue[0]
|
||||||
|
|
||||||
|
# if we're receiving move requests during a PTZ move, ignore them
|
||||||
|
if ptz_moving_at_frame_time(
|
||||||
|
frame_time,
|
||||||
|
self.ptz_metrics[camera]["ptz_start_time"].value,
|
||||||
|
self.ptz_metrics[camera]["ptz_stop_time"].value,
|
||||||
|
):
|
||||||
|
self.move_queues[camera].get()
|
||||||
|
|
||||||
|
# instead of dequeueing this might be a good place to preemptively move based
|
||||||
|
# on an estimate - for fast moving objects, etc.
|
||||||
|
logger.debug(
|
||||||
|
f"Move queue: PTZ moving, dequeueing move request - frame time: {frame_time}, queued pan: {queued_pan}, queued tilt: {queued_tilt}, final pan: {pan}, final tilt: {tilt}"
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# TODO: this may need rethinking
|
||||||
|
logger.debug(
|
||||||
|
f"Move queue: PTZ NOT moving, frame time: {frame_time}, queued pan: {queued_pan}, queued tilt: {queued_tilt}, final pan: {pan}, final tilt: {tilt}"
|
||||||
|
)
|
||||||
|
_, queued_pan, queued_tilt = self.move_queues[camera].get()
|
||||||
|
|
||||||
# If exceeding the movement range, keep it in the queue and move now
|
# If exceeding the movement range, keep it in the queue and move now
|
||||||
if abs(pan + queued_pan) > 1.0 or abs(tilt + queued_tilt) > 1.0:
|
if (
|
||||||
|
abs(pan + queued_pan) > 1.0
|
||||||
|
or abs(tilt + queued_tilt) > 1.0
|
||||||
|
):
|
||||||
logger.debug("Pan or tilt value exceeds 1.0")
|
logger.debug("Pan or tilt value exceeds 1.0")
|
||||||
break
|
break
|
||||||
|
|
||||||
queued_pan, queued_tilt = self.move_queues[camera].get()
|
|
||||||
|
|
||||||
pan += queued_pan
|
pan += queued_pan
|
||||||
tilt += queued_tilt
|
tilt += queued_tilt
|
||||||
|
|
||||||
else:
|
else:
|
||||||
move_data = self.move_queues[camera].get()
|
move_data = self.move_queues[camera].get()
|
||||||
pan, tilt = move_data
|
frame_time, pan, tilt = move_data
|
||||||
|
|
||||||
|
# on some cameras with cheaper motors it seems like small values can cause jerky movement
|
||||||
|
# TODO: double check, might not need this
|
||||||
|
if abs(pan) > 0.02 or abs(tilt) > 0.02:
|
||||||
self.onvif._move_relative(camera, pan, tilt, 1)
|
self.onvif._move_relative(camera, pan, tilt, 1)
|
||||||
|
else:
|
||||||
|
logger.debug(f"Not moving, pan and tilt too small: {pan}, {tilt}")
|
||||||
|
|
||||||
# Wait until the camera finishes moving
|
# Wait until the camera finishes moving
|
||||||
while not self.ptz_metrics[camera]["ptz_stopped"].is_set():
|
while not self.ptz_metrics[camera]["ptz_stopped"].is_set():
|
||||||
# check if ptz is moving
|
# check if ptz is moving
|
||||||
self.onvif.get_camera_status(camera)
|
self.onvif.get_camera_status(camera)
|
||||||
time.sleep(1 / (self.config.cameras[camera].detect.fps / 2))
|
|
||||||
|
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
def _enqueue_move(self, camera, pan, tilt):
|
def _enqueue_move(self, camera, frame_time, pan, tilt):
|
||||||
move_data = (pan, tilt)
|
move_data = (frame_time, pan, tilt)
|
||||||
|
if (
|
||||||
|
frame_time > self.ptz_metrics[camera]["ptz_start_time"].value
|
||||||
|
and frame_time > self.ptz_metrics[camera]["ptz_stop_time"].value
|
||||||
|
):
|
||||||
logger.debug(f"enqueue pan: {pan}, enqueue tilt: {tilt}")
|
logger.debug(f"enqueue pan: {pan}, enqueue tilt: {tilt}")
|
||||||
self.move_queues[camera].put(move_data)
|
self.move_queues[camera].put(move_data)
|
||||||
|
|
||||||
@ -242,12 +276,12 @@ class PtzAutoTracker:
|
|||||||
camera_width = camera_config.frame_shape[1]
|
camera_width = camera_config.frame_shape[1]
|
||||||
camera_height = camera_config.frame_shape[0]
|
camera_height = camera_config.frame_shape[0]
|
||||||
|
|
||||||
# Normalize coordinates. top right of the fov is (1,1).
|
# Normalize coordinates. top right of the fov is (1,1), center is (0,0), bottom left is (-1, -1).
|
||||||
pan = 0.5 - (obj.obj_data["centroid"][0] / camera_width)
|
pan = ((obj.obj_data["centroid"][0] / camera_width) - 0.5) * 2
|
||||||
tilt = 0.5 - (obj.obj_data["centroid"][1] / camera_height)
|
tilt = (0.5 - (obj.obj_data["centroid"][1] / camera_height)) * 2
|
||||||
|
|
||||||
# ideas: check object velocity for camera speed?
|
# ideas: check object velocity for camera speed?
|
||||||
self._enqueue_move(camera, -pan, tilt)
|
self._enqueue_move(camera, obj.obj_data["frame_time"], pan, tilt)
|
||||||
|
|
||||||
def autotrack_object(self, camera, obj):
|
def autotrack_object(self, camera, obj):
|
||||||
camera_config = self.config.cameras[camera]
|
camera_config = self.config.cameras[camera]
|
||||||
@ -274,10 +308,7 @@ class PtzAutoTracker:
|
|||||||
)
|
)
|
||||||
self.tracked_object[camera] = obj
|
self.tracked_object[camera] = obj
|
||||||
self.tracked_object_previous[camera] = copy.deepcopy(obj)
|
self.tracked_object_previous[camera] = copy.deepcopy(obj)
|
||||||
# only enqueue another move if the camera isn't moving
|
self.previous_frame_time = obj.obj_data["frame_time"]
|
||||||
if self.ptz_metrics[camera]["ptz_stopped"].is_set():
|
|
||||||
self.ptz_metrics[camera]["ptz_stopped"].clear()
|
|
||||||
logger.debug("Autotrack: New object, moving ptz")
|
|
||||||
self._autotrack_move_ptz(camera, obj)
|
self._autotrack_move_ptz(camera, obj)
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -287,9 +318,9 @@ class PtzAutoTracker:
|
|||||||
self.tracked_object[camera] is not None
|
self.tracked_object[camera] is not None
|
||||||
and self.tracked_object_previous[camera] is not None
|
and self.tracked_object_previous[camera] is not None
|
||||||
and obj.obj_data["id"] == self.tracked_object[camera].obj_data["id"]
|
and obj.obj_data["id"] == self.tracked_object[camera].obj_data["id"]
|
||||||
and obj.obj_data["frame_time"]
|
and obj.obj_data["frame_time"] != self.previous_frame_time
|
||||||
!= self.tracked_object_previous[camera].obj_data["frame_time"]
|
|
||||||
):
|
):
|
||||||
|
self.previous_frame_time = obj.obj_data["frame_time"]
|
||||||
# Don't move ptz if Euclidean distance from object to center of frame is
|
# Don't move ptz if Euclidean distance from object to center of frame is
|
||||||
# less than 15% of the of the larger dimension (width or height) of the frame,
|
# less than 15% of the of the larger dimension (width or height) of the frame,
|
||||||
# multiplied by a scaling factor for object size.
|
# multiplied by a scaling factor for object size.
|
||||||
@ -323,9 +354,7 @@ class PtzAutoTracker:
|
|||||||
f"Distance: {distance}, threshold: {distance_threshold}, iou: {iou}"
|
f"Distance: {distance}, threshold: {distance_threshold}, iou: {iou}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if (distance < distance_threshold or iou > 0.5) and self.ptz_metrics[
|
if distance < distance_threshold and iou > 0.2:
|
||||||
camera
|
|
||||||
]["ptz_stopped"].is_set():
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"Autotrack: Existing object (do NOT move ptz): {obj.obj_data['id']} {obj.obj_data['box']} {obj.obj_data['frame_time']}"
|
f"Autotrack: Existing object (do NOT move ptz): {obj.obj_data['id']} {obj.obj_data['box']} {obj.obj_data['frame_time']}"
|
||||||
)
|
)
|
||||||
@ -335,11 +364,6 @@ class PtzAutoTracker:
|
|||||||
f"Autotrack: Existing object (need to move ptz): {obj.obj_data['id']} {obj.obj_data['box']} {obj.obj_data['frame_time']}"
|
f"Autotrack: Existing object (need to move ptz): {obj.obj_data['id']} {obj.obj_data['box']} {obj.obj_data['frame_time']}"
|
||||||
)
|
)
|
||||||
self.tracked_object_previous[camera] = copy.deepcopy(obj)
|
self.tracked_object_previous[camera] = copy.deepcopy(obj)
|
||||||
|
|
||||||
# only enqueue another move if the camera isn't moving
|
|
||||||
if self.ptz_metrics[camera]["ptz_stopped"].is_set():
|
|
||||||
self.ptz_metrics[camera]["ptz_stopped"].clear()
|
|
||||||
logger.debug("Autotrack: Existing object, moving ptz")
|
|
||||||
self._autotrack_move_ptz(camera, obj)
|
self._autotrack_move_ptz(camera, obj)
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -356,6 +380,7 @@ class PtzAutoTracker:
|
|||||||
and obj.obj_data["motionless_count"] == 0
|
and obj.obj_data["motionless_count"] == 0
|
||||||
and self.tracked_object_previous[camera] is not None
|
and self.tracked_object_previous[camera] is not None
|
||||||
):
|
):
|
||||||
|
self.previous_frame_time = obj.obj_data["frame_time"]
|
||||||
if (
|
if (
|
||||||
intersection_over_union(
|
intersection_over_union(
|
||||||
self.tracked_object_previous[camera].obj_data["region"],
|
self.tracked_object_previous[camera].obj_data["region"],
|
||||||
@ -368,10 +393,6 @@ class PtzAutoTracker:
|
|||||||
)
|
)
|
||||||
self.tracked_object[camera] = obj
|
self.tracked_object[camera] = obj
|
||||||
self.tracked_object_previous[camera] = copy.deepcopy(obj)
|
self.tracked_object_previous[camera] = copy.deepcopy(obj)
|
||||||
# only enqueue another move if the camera isn't moving
|
|
||||||
if self.ptz_metrics[camera]["ptz_stopped"].is_set():
|
|
||||||
self.ptz_metrics[camera]["ptz_stopped"].clear()
|
|
||||||
logger.debug("Autotrack: Reacquired object, moving ptz")
|
|
||||||
self._autotrack_move_ptz(camera, obj)
|
self._autotrack_move_ptz(camera, obj)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user