From b158c16c134a163b8a6b2c1a2d31e8d320ae01ea Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Wed, 31 May 2023 08:19:14 -0500 Subject: [PATCH] update distance calculation --- .devcontainer/devcontainer.json | 7 ++-- frigate/track/centroid_tracker.py | 2 +- frigate/track/norfair_tracker.py | 56 +++++++++++++++++++++---------- frigate/track/sort_tracker.py | 8 ++--- frigate/video.py | 2 -- 5 files changed, 47 insertions(+), 28 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 60065a965..a8264a227 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -53,7 +53,8 @@ "csstools.postcss", "blanu.vscode-styled-jsx", "bradlc.vscode-tailwindcss", - "ms-python.isort" + "ms-python.isort", + "charliermarsh.ruff" ], "settings": { "remote.autoForwardPorts": false, @@ -69,9 +70,7 @@ "python.testing.unittestArgs": ["-v", "-s", "./frigate/test"], "files.trimTrailingWhitespace": true, "eslint.workingDirectories": ["./web"], - "isort.args": [ - "--settings-path=./pyproject.toml" - ], + "isort.args": ["--settings-path=./pyproject.toml"], "[python]": { "editor.defaultFormatter": "ms-python.black-formatter", "editor.formatOnSave": true diff --git a/frigate/track/centroid_tracker.py b/frigate/track/centroid_tracker.py index 8a210e2cb..fd4a293f9 100644 --- a/frigate/track/centroid_tracker.py +++ b/frigate/track/centroid_tracker.py @@ -4,8 +4,8 @@ from collections import defaultdict import numpy as np from scipy.spatial import distance as dist -from frigate.config import DetectConfig +from frigate.config import DetectConfig from frigate.track import ObjectTracker from frigate.util import intersection_over_union diff --git a/frigate/track/norfair_tracker.py b/frigate/track/norfair_tracker.py index a6e94071f..0990f6563 100644 --- a/frigate/track/norfair_tracker.py +++ b/frigate/track/norfair_tracker.py @@ -1,13 +1,13 @@ -from collections import defaultdict import random import string 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.track import ObjectTracker from frigate.util import intersection_over_union -from norfair import Detection, Tracker, Drawable, draw_boxes -from norfair.drawing.drawer import Drawer # Normalizes distance from estimate relative to object size @@ -16,17 +16,41 @@ from norfair.drawing.drawer import Drawer # - could be variable based on time since last_detection # - include estimated velocity in the distance (car driving by of a parked car) # - include some visual similarity factor in the distance for occlusions -def frigate_distance(detection: Detection, tracked_object) -> float: - # calculate distances and normalize it by width and height of previous detection - ld = tracked_object.last_detection - width = ld.points[1][0] - ld.points[0][0] - height = ld.points[1][1] - ld.points[0][1] - difference = (detection.points - tracked_object.estimate).astype(float) - difference[:, 0] /= width - difference[:, 1] /= height +def distance(detection: np.array, estimate: np.array) -> float: + # ultimately, this should try and estimate distance in 3-dimensional space + # consider change in location, width, and height - # calculate euclidean distance and average - return np.linalg.norm(difference, axis=1).mean() + estimate_dim = np.diff(estimate, axis=0).flatten() + detection_dim = np.diff(detection, axis=0).flatten() + + # get centroid positions + detection_position = np.array( + [np.average(detection[:, 0]), np.max(detection[:, 1])] + ) + estimate_position = np.array([np.average(estimate[:, 0]), np.max(estimate[:, 1])]) + + distance = (detection_position - estimate_position).astype(float) + # change in x relative to w + distance[0] /= estimate_dim[0] + # change in y relative to h + distance[1] /= estimate_dim[1] + + # get ratio of widths and heights + # normalize to 1 + widths = np.sort([estimate_dim[0], detection_dim[0]]) + heights = np.sort([estimate_dim[1], detection_dim[1]]) + width_ratio = widths[1] / widths[0] - 1.0 + height_ratio = heights[1] / heights[0] - 1.0 + + # change vector is relative x,y change and w,h ratio + change = np.append(distance, np.array([width_ratio, height_ratio])) + + # calculate euclidean distance of the change vector + return np.linalg.norm(change) + + +def frigate_distance(detection: Detection, tracked_object) -> float: + return distance(detection.points, tracked_object.estimate) class NorfairTracker(ObjectTracker): @@ -41,9 +65,7 @@ class NorfairTracker(ObjectTracker): # was a good reason to have different distance calculations self.tracker = Tracker( distance_function=frigate_distance, - # distance is relative to the size of the last - # detection - distance_threshold=4.0, + distance_threshold=2.5, initialization_delay=0, hit_counter_max=self.max_disappeared, ) @@ -210,7 +232,7 @@ class NorfairTracker(ObjectTracker): active_ids = [] for t in tracked_objects: active_ids.append(t.global_id) - if not t.global_id in self.track_id_map: + if t.global_id not in self.track_id_map: self.register(t.global_id, t.last_detection.data) # if there wasn't a detection in this frame, increment disappeared elif t.last_detection.data["frame_time"] != frame_time: diff --git a/frigate/track/sort_tracker.py b/frigate/track/sort_tracker.py index f05cefc55..e7fe4bfbb 100644 --- a/frigate/track/sort_tracker.py +++ b/frigate/track/sort_tracker.py @@ -1,12 +1,12 @@ -from collections import defaultdict import random import string import numpy as np +from similari import BoundingBox, PositionalMetricType, Sort, SpatioTemporalConstraints + from frigate.config import DetectConfig from frigate.track import ObjectTracker from frigate.util import intersection_over_union -from similari import Sort, BoundingBox, SpatioTemporalConstraints, PositionalMetricType class SortTracker(ObjectTracker): @@ -156,7 +156,7 @@ class SortTracker(ObjectTracker): # get the scene_id for this label or create a new one # TODO: consider grouping frequently swapped objects in # in the same scene - if not obj[0] in self.scene_map: + if obj[0] not in self.scene_map: scene_id = len(self.scene_map.keys()) self.scene_map[obj[0]] = scene_id scene_detections[scene_id] = [] @@ -200,7 +200,7 @@ class SortTracker(ObjectTracker): # update or create new tracks for t in tracks: - if not t.id in self.track_id_map: + if t.id not in self.track_id_map: self.register(t.id, objs[t.custom_object_id]) else: self.update(t.id, objs[t.custom_object_id]) diff --git a/frigate/video.py b/frigate/video.py index 677b4a177..08808038e 100755 --- a/frigate/video.py +++ b/frigate/video.py @@ -20,9 +20,7 @@ from frigate.log import LogPipe from frigate.motion import MotionDetector from frigate.object_detection import RemoteObjectDetector from frigate.track import ObjectTracker -from frigate.track.centroid_tracker import CentroidTracker from frigate.track.norfair_tracker import NorfairTracker -from frigate.track.sort_tracker import SortTracker from frigate.util import ( EventsPerSecond, FrameManager,