Skip to content

Commit

Permalink
Don't use distance functions for unmatched trackers
Browse files Browse the repository at this point in the history
  • Loading branch information
Agustín Castro committed Mar 8, 2024
1 parent cdd3e58 commit 6eb462e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 21 deletions.
13 changes: 6 additions & 7 deletions demos/multi_camera/src/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,10 @@ def run():
help="Minimum age of a cluster (or it's objects) to be returned",
)
parser.add_argument(
"--filter-by-objects-age",
type=bool,
default=False,
help="Filter cluster by their objects age, instead of the clusters age.",
"--maximum-time-since-last-update",
type=int,
default=1,
help="Filter tracked objects that were not detected recently to not be considered in the distance function of the clusterizer",
)
parser.add_argument(
"--hit-counter-max",
Expand All @@ -344,7 +344,7 @@ def run():
parser.add_argument(
"--reid-hit-counter-max",
type=int,
default=300,
default=500,
help="Maximum amount of frames trying to reidentify the object. (Use a value >=0)",
)
parser.add_argument(
Expand Down Expand Up @@ -521,7 +521,6 @@ def conditional_embedding_to_spatial(detection, tracked_object):
reid_distance_function=embedding_distance,
reid_distance_threshold=args.reid_embedding_correlation_threshold,
reid_hit_counter_max=args.reid_hit_counter_max,
pointwise_hit_counter_max=2,
)
tracked_objects[path] = []

Expand Down Expand Up @@ -562,7 +561,7 @@ def clusterizer_distance(tracker1, tracker2):
memory=args.memory,
initialization_delay=args.clusterizer_initialization_delay,
reid_hit_counter_max=args.reid_hit_counter_max,
use_only_living_trackers=False,
maximum_time_since_last_update=args.maximum_time_since_last_update,
)

while True:
Expand Down
62 changes: 48 additions & 14 deletions norfair/multi_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ def flatten_list(nested_list):
return list(itertools.chain(*nested_list))


def redefine_distance(distance_function, distance_same_camera):
def redefine_distance(
distance_function,
distance_same_camera,
distance_threshold,
clusters,
maximum_time_since_last_update,
):
"""
In order to not match trackers of the same camera, we need to make sure that the
distance between objects of the same camera is at least:
Expand All @@ -19,8 +25,32 @@ def redefine_distance(distance_function, distance_same_camera):
def new_distance(tracked_object_1, tracked_object_2):
if tracked_object_1.camera_name == tracked_object_2.camera_name:
return distance_same_camera
else:
return distance_function(tracked_object_1, tracked_object_2)
elif not (
(
(
tracked_object_1.point_hit_counter
>= tracked_object_1.hit_counter_max - maximum_time_since_last_update
).any()
)
and (
(
tracked_object_2.point_hit_counter
>= tracked_object_2.hit_counter_max - maximum_time_since_last_update
).any()
)
):
for cluster in clusters:
current_ids = {
(tracked_object_1.camera_name, tracked_object_1.id),
(tracked_object_2.camera_name, tracked_object_2.id),
}
if len(current_ids.intersection(set(cluster.tracked_ids))) == 2:
return min(
distance_threshold * 0.99,
distance_function(tracked_object_1, tracked_object_2),
)

return distance_function(tracked_object_1, tracked_object_2)

return new_distance

Expand Down Expand Up @@ -135,20 +165,23 @@ def generate_current_clusters(
trackers_by_camera,
distance_function,
distance_threshold,
clusters,
join_distance_by="mean",
use_only_living_trackers=False,
maximum_time_since_last_update=1,
):

# In case number of camera is variable, I will redefine the distance function
distance_same_camera = len(trackers_by_camera) ** 2 * distance_threshold + 1
distance_function = redefine_distance(distance_function, distance_same_camera)
distance_function = redefine_distance(
distance_function,
distance_same_camera,
distance_threshold,
clusters,
maximum_time_since_last_update,
)

current_clusters = flatten_list(trackers_by_camera)

# use only alive trackers:
if use_only_living_trackers:
current_clusters = [obj for obj in current_clusters if obj.live_points.any()]

if len(current_clusters) > 0:
distance_matrix = (
np.zeros((len(current_clusters), len(current_clusters)))
Expand Down Expand Up @@ -441,7 +474,7 @@ def __init__(
memory: int = 3,
initialization_delay: int = 4,
reid_hit_counter_max: int = 0,
use_only_living_trackers: bool = False,
maximum_time_since_last_update: int = 1,
):
"""
Associate trackers from different cameras/videos.
Expand Down Expand Up @@ -479,8 +512,8 @@ def __init__(
If doing reid in the tracking, then provide the reid_hit_counter_max so that the MultiCameraClusterizer instance knows
for how long to keep storing clusters of tracked objects that have dissapeared.
- use_only_living_trackers: bool.
Filter tracked objects that have no alive points. This can be useful since tracked objects that are not alive might have
- maximum_time_since_last_update: int.
Filter tracked objects that were not detected recently. This can be useful since those tracked objects might have
position that will not match well with their position in a different camera.
"""
if max_votes_grow < 1:
Expand Down Expand Up @@ -515,7 +548,7 @@ def __init__(
self.initialization_delay = initialization_delay + max_votes_grow

self.reid_hit_counter_max = reid_hit_counter_max + 1
self.use_only_living_trackers = use_only_living_trackers
self.maximum_time_since_last_update = maximum_time_since_last_update

def update(self, trackers_by_camera):

Expand All @@ -536,8 +569,9 @@ def update(self, trackers_by_camera):
trackers_by_camera,
self.distance_function,
self.distance_threshold,
self.clusters,
self.join_distance_by,
self.use_only_living_trackers,
self.maximum_time_since_last_update,
)
self.past_clusters.insert(0, deepcopy(current_clusters))

Expand Down

0 comments on commit 6eb462e

Please sign in to comment.