mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-07 11:45:24 +03:00
refactor thresholds and reduce a duplicate call
This commit is contained in:
parent
5a46c36380
commit
1a7344603e
@ -502,7 +502,7 @@ class PtzAutoTracker:
|
|||||||
|
|
||||||
return np.dot(self.move_coefficients[camera], input_data)
|
return np.dot(self.move_coefficients[camera], input_data)
|
||||||
|
|
||||||
def _calculate_tracked_object_metrics(self, camera):
|
def _calculate_tracked_object_metrics(self, camera, obj):
|
||||||
def remove_outliers(data):
|
def remove_outliers(data):
|
||||||
Q1 = np.percentile(data, 25)
|
Q1 = np.percentile(data, 25)
|
||||||
Q3 = np.percentile(data, 75)
|
Q3 = np.percentile(data, 75)
|
||||||
@ -541,6 +541,27 @@ class PtzAutoTracker:
|
|||||||
"original_target_box"
|
"original_target_box"
|
||||||
] = self.tracked_object_metrics[camera]["target_box"]
|
] = self.tracked_object_metrics[camera]["target_box"]
|
||||||
|
|
||||||
|
(
|
||||||
|
self.tracked_object_metrics[camera]["valid_velocity"],
|
||||||
|
self.tracked_object_metrics[camera]["velocity"],
|
||||||
|
) = self._get_valid_velocity(camera, obj)
|
||||||
|
self.tracked_object_metrics[camera]["distance"] = self._get_distance_threshold(
|
||||||
|
camera, obj
|
||||||
|
)
|
||||||
|
|
||||||
|
centroid_distance = np.linalg.norm(
|
||||||
|
[
|
||||||
|
obj.obj_data["centroid"][0] - camera_config.detect.width / 2,
|
||||||
|
obj.obj_data["centroid"][1] - camera_config.detect.height / 2,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.debug(f"{camera}: Centroid distance: {centroid_distance}")
|
||||||
|
|
||||||
|
self.tracked_object_metrics[camera]["below_distance_threshold"] = (
|
||||||
|
centroid_distance < self.tracked_object_metrics[camera]["distance"]
|
||||||
|
)
|
||||||
|
|
||||||
def _process_move_queue(self, camera):
|
def _process_move_queue(self, camera):
|
||||||
camera_config = self.config.cameras[camera]
|
camera_config = self.config.cameras[camera]
|
||||||
camera_config.frame_shape[1]
|
camera_config.frame_shape[1]
|
||||||
@ -668,12 +689,16 @@ class PtzAutoTracker:
|
|||||||
velocities = obj.obj_data["estimate_velocity"]
|
velocities = obj.obj_data["estimate_velocity"]
|
||||||
logger.debug(f"{camera}: Velocities from norfair: {velocities}")
|
logger.debug(f"{camera}: Velocities from norfair: {velocities}")
|
||||||
|
|
||||||
|
# if we are close enough to zero, return right away
|
||||||
|
if np.all(np.round(velocities) == 0):
|
||||||
|
return True, np.zeros((2, 2))
|
||||||
|
|
||||||
# Thresholds
|
# Thresholds
|
||||||
x_mags_thresh = camera_width / camera_fps / 2
|
x_mags_thresh = camera_width / camera_fps / 2
|
||||||
y_mags_thresh = camera_height / camera_fps / 2
|
y_mags_thresh = camera_height / camera_fps / 2
|
||||||
dir_thresh = 0.96
|
dir_thresh = 0.93
|
||||||
delta_thresh = 10
|
delta_thresh = 12
|
||||||
var_thresh = 3
|
var_thresh = 5
|
||||||
|
|
||||||
# Check magnitude
|
# Check magnitude
|
||||||
x_mags = np.abs(velocities[:, 0])
|
x_mags = np.abs(velocities[:, 0])
|
||||||
@ -690,11 +715,15 @@ class PtzAutoTracker:
|
|||||||
high_variances = np.any(stdevs > var_thresh)
|
high_variances = np.any(stdevs > var_thresh)
|
||||||
|
|
||||||
# Check direction difference
|
# Check direction difference
|
||||||
cosine_sim = np.dot(velocities[0], velocities[1]) / (
|
velocities = np.round(velocities)
|
||||||
np.linalg.norm(velocities[0]) * np.linalg.norm(velocities[1])
|
invalid_dirs = False
|
||||||
)
|
if not np.any(np.linalg.norm(velocities, axis=1)):
|
||||||
dir_thresh = 0.6 if np.all(delta < delta_thresh / 2) else dir_thresh
|
cosine_sim = np.dot(velocities[0], velocities[1]) / (
|
||||||
invalid_dirs = cosine_sim < dir_thresh
|
np.linalg.norm(velocities[0]) * np.linalg.norm(velocities[1])
|
||||||
|
)
|
||||||
|
dir_thresh = 0.6 if np.all(delta < delta_thresh / 2) else dir_thresh
|
||||||
|
print(f"cosine sim: {cosine_sim}")
|
||||||
|
invalid_dirs = cosine_sim < dir_thresh
|
||||||
|
|
||||||
# Combine
|
# Combine
|
||||||
invalid = (
|
invalid = (
|
||||||
@ -723,11 +752,12 @@ class PtzAutoTracker:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
# invalid velocity
|
# invalid velocity
|
||||||
return np.zeros((2, 2))
|
return False, np.zeros((2, 2))
|
||||||
else:
|
else:
|
||||||
return np.mean(velocities, axis=0)
|
logger.debug(f"{camera}: Valid velocity ")
|
||||||
|
return True, np.mean(velocities, axis=0)
|
||||||
|
|
||||||
def _below_distance_threshold(self, camera, obj):
|
def _get_distance_threshold(self, camera, obj):
|
||||||
# Returns true if Euclidean distance from object to center of frame is
|
# Returns true if Euclidean distance from object to center of frame is
|
||||||
# less than 10% of the of the larger dimension (width or height) of the frame,
|
# less than 10% 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.
|
||||||
@ -738,13 +768,6 @@ class PtzAutoTracker:
|
|||||||
# TODO: there's probably a better way to approach this
|
# TODO: there's probably a better way to approach this
|
||||||
camera_config = self.config.cameras[camera]
|
camera_config = self.config.cameras[camera]
|
||||||
|
|
||||||
centroid_distance = np.linalg.norm(
|
|
||||||
[
|
|
||||||
obj.obj_data["centroid"][0] - camera_config.detect.width / 2,
|
|
||||||
obj.obj_data["centroid"][1] - camera_config.detect.height / 2,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
obj_width = obj.obj_data["box"][2] - obj.obj_data["box"][0]
|
obj_width = obj.obj_data["box"][2] - obj.obj_data["box"][0]
|
||||||
obj_height = obj.obj_data["box"][3] - obj.obj_data["box"][1]
|
obj_height = obj.obj_data["box"][3] - obj.obj_data["box"][1]
|
||||||
|
|
||||||
@ -758,14 +781,17 @@ class PtzAutoTracker:
|
|||||||
# larger objects should lower the threshold, smaller objects should raise it
|
# larger objects should lower the threshold, smaller objects should raise it
|
||||||
scaling_factor = 1 - np.log(max_obj / max_frame)
|
scaling_factor = 1 - np.log(max_obj / max_frame)
|
||||||
|
|
||||||
percentage = 0.1 if camera_config.onvif.autotracking.movement_weights else 0.03
|
percentage = (
|
||||||
|
0.08
|
||||||
|
if camera_config.onvif.autotracking.movement_weights
|
||||||
|
and self.tracked_object_metrics[camera]["valid_velocity"]
|
||||||
|
else 0.03
|
||||||
|
)
|
||||||
distance_threshold = percentage * max_frame * scaling_factor
|
distance_threshold = percentage * max_frame * scaling_factor
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(f"{camera}: Distance threshold: {distance_threshold}")
|
||||||
f"{camera}: Distance: {centroid_distance}, threshold: {distance_threshold}"
|
|
||||||
)
|
|
||||||
|
|
||||||
return centroid_distance < distance_threshold
|
return distance_threshold
|
||||||
|
|
||||||
def _should_zoom_in(self, camera, obj, box, debug_zooming=False):
|
def _should_zoom_in(self, camera, obj, box, debug_zooming=False):
|
||||||
# returns True if we should zoom in, False if we should zoom out, None to do nothing
|
# returns True if we should zoom in, False if we should zoom out, None to do nothing
|
||||||
@ -774,7 +800,7 @@ class PtzAutoTracker:
|
|||||||
camera_height = camera_config.frame_shape[0]
|
camera_height = camera_config.frame_shape[0]
|
||||||
camera_fps = camera_config.detect.fps
|
camera_fps = camera_config.detect.fps
|
||||||
|
|
||||||
average_velocity = self._get_valid_velocity(camera, obj)
|
average_velocity = self.tracked_object_metrics[camera]["velocity"]
|
||||||
|
|
||||||
bb_left, bb_top, bb_right, bb_bottom = box
|
bb_left, bb_top, bb_right, bb_bottom = box
|
||||||
|
|
||||||
@ -799,7 +825,9 @@ class PtzAutoTracker:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# make sure object is centered in the frame
|
# make sure object is centered in the frame
|
||||||
below_distance_threshold = self._below_distance_threshold(camera, obj)
|
below_distance_threshold = self.tracked_object_metrics[camera][
|
||||||
|
"below_distance_threshold"
|
||||||
|
]
|
||||||
|
|
||||||
below_dimension_threshold = (bb_right - bb_left) <= camera_width * (
|
below_dimension_threshold = (bb_right - bb_left) <= camera_width * (
|
||||||
self.zoom_factor[camera] + 0.1
|
self.zoom_factor[camera] + 0.1
|
||||||
@ -925,7 +953,14 @@ class PtzAutoTracker:
|
|||||||
): # use estimates if we have available coefficients
|
): # use estimates if we have available coefficients
|
||||||
predicted_movement_time = self._predict_movement_time(camera, pan, tilt)
|
predicted_movement_time = self._predict_movement_time(camera, pan, tilt)
|
||||||
|
|
||||||
average_velocity = self._get_valid_velocity(camera, obj)
|
_, average_velocity = (
|
||||||
|
self._get_valid_velocity(camera, obj)
|
||||||
|
if "velocity" not in self.tracked_object_metrics[camera]
|
||||||
|
else (
|
||||||
|
self.tracked_object_metrics[camera]["valid_velocity"],
|
||||||
|
self.tracked_object_metrics[camera]["velocity"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if np.any(average_velocity):
|
if np.any(average_velocity):
|
||||||
# this box could exceed the frame boundaries if velocity is high
|
# this box could exceed the frame boundaries if velocity is high
|
||||||
@ -992,7 +1027,7 @@ class PtzAutoTracker:
|
|||||||
level = (
|
level = (
|
||||||
self.ptz_metrics[camera]["ptz_max_zoom"].value
|
self.ptz_metrics[camera]["ptz_max_zoom"].value
|
||||||
- self.ptz_metrics[camera]["ptz_min_zoom"].value
|
- self.ptz_metrics[camera]["ptz_min_zoom"].value
|
||||||
) / 10
|
) / 20
|
||||||
if result:
|
if result:
|
||||||
zoom = min(1.0, current_zoom_level + level)
|
zoom = min(1.0, current_zoom_level + level)
|
||||||
else:
|
else:
|
||||||
@ -1103,9 +1138,9 @@ class PtzAutoTracker:
|
|||||||
)
|
)
|
||||||
):
|
):
|
||||||
self.tracked_object_history[camera].append(copy.deepcopy(obj.obj_data))
|
self.tracked_object_history[camera].append(copy.deepcopy(obj.obj_data))
|
||||||
self._calculate_tracked_object_metrics(camera)
|
self._calculate_tracked_object_metrics(camera, obj)
|
||||||
|
|
||||||
if self._below_distance_threshold(camera, obj):
|
if self.tracked_object_metrics[camera]["below_distance_threshold"]:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"{camera}: Existing object (do NOT move ptz): {obj.obj_data['id']} {obj.obj_data['box']} {obj.obj_data['frame_time']}"
|
f"{camera}: Existing object (do NOT move ptz): {obj.obj_data['id']} {obj.obj_data['box']} {obj.obj_data['frame_time']}"
|
||||||
)
|
)
|
||||||
@ -1148,7 +1183,7 @@ class PtzAutoTracker:
|
|||||||
self.tracked_object_history[camera].append(
|
self.tracked_object_history[camera].append(
|
||||||
copy.deepcopy(obj.obj_data)
|
copy.deepcopy(obj.obj_data)
|
||||||
)
|
)
|
||||||
self._calculate_tracked_object_metrics(camera)
|
self._calculate_tracked_object_metrics(camera, obj)
|
||||||
self._autotrack_move_ptz(camera, obj)
|
self._autotrack_move_ptz(camera, obj)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user