mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
group by label before tracking objects
This commit is contained in:
parent
32b212c7b6
commit
be5a114f6a
@ -251,6 +251,7 @@ class ObjectTracker(threading.Thread):
|
|||||||
|
|
||||||
def register(self, index, obj):
|
def register(self, index, obj):
|
||||||
id = f"{str(obj['frame_time'])}-{index}"
|
id = f"{str(obj['frame_time'])}-{index}"
|
||||||
|
obj['id'] = id
|
||||||
self.tracked_objects[id] = obj
|
self.tracked_objects[id] = obj
|
||||||
self.disappeared[id] = 0
|
self.disappeared[id] = 0
|
||||||
|
|
||||||
@ -281,95 +282,105 @@ class ObjectTracker(threading.Thread):
|
|||||||
# to update
|
# to update
|
||||||
return
|
return
|
||||||
|
|
||||||
# compute centroids
|
# group by name
|
||||||
|
new_object_groups = defaultdict(lambda: [])
|
||||||
for obj in new_objects:
|
for obj in new_objects:
|
||||||
centroid_x = int((obj['box']['xmin']+obj['box']['xmax']) / 2.0)
|
new_object_groups[obj['name']].append(obj)
|
||||||
centroid_y = int((obj['box']['ymin']+obj['box']['ymax']) / 2.0)
|
|
||||||
obj['centroid'] = (centroid_x, centroid_y)
|
|
||||||
|
|
||||||
if len(self.tracked_objects) == 0:
|
# track objects for each label type
|
||||||
for index, obj in enumerate(new_objects):
|
# TODO: this is going to miss deregistering objects that are not in the new groups
|
||||||
self.register(index, obj)
|
for label, group in new_object_groups.items():
|
||||||
return
|
current_objects = [o for o in self.tracked_objects.values() if o['name'] == label]
|
||||||
|
current_ids = [o['id'] for o in current_objects]
|
||||||
|
current_centroids = np.array([o['centroid'] for o in current_objects])
|
||||||
|
|
||||||
new_centroids = np.array([o['centroid'] for o in new_objects])
|
# compute centroids
|
||||||
current_ids = list(self.tracked_objects.keys())
|
for obj in group:
|
||||||
current_centroids = np.array([o['centroid'] for o in self.tracked_objects.values()])
|
centroid_x = int((obj['box']['xmin']+obj['box']['xmax']) / 2.0)
|
||||||
|
centroid_y = int((obj['box']['ymin']+obj['box']['ymax']) / 2.0)
|
||||||
|
obj['centroid'] = (centroid_x, centroid_y)
|
||||||
|
|
||||||
# compute the distance between each pair of tracked
|
if len(current_objects) == 0:
|
||||||
# centroids and new centroids, respectively -- our
|
for index, obj in enumerate(group):
|
||||||
# goal will be to match each new centroid to an existing
|
self.register(index, obj)
|
||||||
# object centroid
|
return
|
||||||
D = dist.cdist(current_centroids, new_centroids)
|
|
||||||
|
|
||||||
# in order to perform this matching we must (1) find the
|
new_centroids = np.array([o['centroid'] for o in group])
|
||||||
# smallest value in each row and then (2) sort the row
|
|
||||||
# indexes based on their minimum values so that the row
|
|
||||||
# with the smallest value is at the *front* of the index
|
|
||||||
# list
|
|
||||||
rows = D.min(axis=1).argsort()
|
|
||||||
|
|
||||||
# next, we perform a similar process on the columns by
|
# compute the distance between each pair of tracked
|
||||||
# finding the smallest value in each column and then
|
# centroids and new centroids, respectively -- our
|
||||||
# sorting using the previously computed row index list
|
# goal will be to match each new centroid to an existing
|
||||||
cols = D.argmin(axis=1)[rows]
|
# object centroid
|
||||||
|
D = dist.cdist(current_centroids, new_centroids)
|
||||||
|
|
||||||
# in order to determine if we need to update, register,
|
# in order to perform this matching we must (1) find the
|
||||||
# or deregister an object we need to keep track of which
|
# smallest value in each row and then (2) sort the row
|
||||||
# of the rows and column indexes we have already examined
|
# indexes based on their minimum values so that the row
|
||||||
usedRows = set()
|
# with the smallest value is at the *front* of the index
|
||||||
usedCols = set()
|
# list
|
||||||
|
rows = D.min(axis=1).argsort()
|
||||||
|
|
||||||
# loop over the combination of the (row, column) index
|
# next, we perform a similar process on the columns by
|
||||||
# tuples
|
# finding the smallest value in each column and then
|
||||||
for (row, col) in zip(rows, cols):
|
# sorting using the previously computed row index list
|
||||||
# if we have already examined either the row or
|
cols = D.argmin(axis=1)[rows]
|
||||||
# column value before, ignore it
|
|
||||||
# val
|
|
||||||
if row in usedRows or col in usedCols:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# otherwise, grab the object ID for the current row,
|
# in order to determine if we need to update, register,
|
||||||
# set its new centroid, and reset the disappeared
|
# or deregister an object we need to keep track of which
|
||||||
# counter
|
# of the rows and column indexes we have already examined
|
||||||
objectID = current_ids[row]
|
usedRows = set()
|
||||||
self.update(objectID, new_objects[col])
|
usedCols = set()
|
||||||
self.disappeared[objectID] = 0
|
|
||||||
|
|
||||||
# indicate that we have examined each of the row and
|
# loop over the combination of the (row, column) index
|
||||||
# column indexes, respectively
|
# tuples
|
||||||
usedRows.add(row)
|
for (row, col) in zip(rows, cols):
|
||||||
usedCols.add(col)
|
# if we have already examined either the row or
|
||||||
|
# column value before, ignore it
|
||||||
|
# val
|
||||||
|
if row in usedRows or col in usedCols:
|
||||||
|
continue
|
||||||
|
|
||||||
# compute both the row and column index we have NOT yet
|
# otherwise, grab the object ID for the current row,
|
||||||
# examined
|
# set its new centroid, and reset the disappeared
|
||||||
unusedRows = set(range(0, D.shape[0])).difference(usedRows)
|
# counter
|
||||||
unusedCols = set(range(0, D.shape[1])).difference(usedCols)
|
|
||||||
|
|
||||||
# in the event that the number of object centroids is
|
|
||||||
# equal or greater than the number of input centroids
|
|
||||||
# we need to check and see if some of these objects have
|
|
||||||
# potentially disappeared
|
|
||||||
if D.shape[0] >= D.shape[1]:
|
|
||||||
# loop over the unused row indexes
|
|
||||||
for row in unusedRows:
|
|
||||||
# grab the object ID for the corresponding row
|
|
||||||
# index and increment the disappeared counter
|
|
||||||
objectID = current_ids[row]
|
objectID = current_ids[row]
|
||||||
self.disappeared[objectID] += 1
|
self.update(objectID, new_objects[col])
|
||||||
|
self.disappeared[objectID] = 0
|
||||||
|
|
||||||
# check to see if the number of consecutive
|
# indicate that we have examined each of the row and
|
||||||
# frames the object has been marked "disappeared"
|
# column indexes, respectively
|
||||||
# for warrants deregistering the object
|
usedRows.add(row)
|
||||||
if self.disappeared[objectID] > self.max_disappeared:
|
usedCols.add(col)
|
||||||
self.deregister(objectID)
|
|
||||||
|
|
||||||
# otherwise, if the number of input centroids is greater
|
# compute both the row and column index we have NOT yet
|
||||||
# than the number of existing object centroids we need to
|
# examined
|
||||||
# register each new input centroid as a trackable object
|
unusedRows = set(range(0, D.shape[0])).difference(usedRows)
|
||||||
else:
|
unusedCols = set(range(0, D.shape[1])).difference(usedCols)
|
||||||
for col in unusedCols:
|
|
||||||
self.register(col, new_objects[col])
|
# in the event that the number of object centroids is
|
||||||
|
# equal or greater than the number of input centroids
|
||||||
|
# we need to check and see if some of these objects have
|
||||||
|
# potentially disappeared
|
||||||
|
if D.shape[0] >= D.shape[1]:
|
||||||
|
# loop over the unused row indexes
|
||||||
|
for row in unusedRows:
|
||||||
|
# grab the object ID for the corresponding row
|
||||||
|
# index and increment the disappeared counter
|
||||||
|
objectID = current_ids[row]
|
||||||
|
self.disappeared[objectID] += 1
|
||||||
|
|
||||||
|
# check to see if the number of consecutive
|
||||||
|
# frames the object has been marked "disappeared"
|
||||||
|
# for warrants deregistering the object
|
||||||
|
if self.disappeared[objectID] > self.max_disappeared:
|
||||||
|
self.deregister(objectID)
|
||||||
|
|
||||||
|
# otherwise, if the number of input centroids is greater
|
||||||
|
# than the number of existing object centroids we need to
|
||||||
|
# register each new input centroid as a trackable object
|
||||||
|
else:
|
||||||
|
for col in unusedCols:
|
||||||
|
self.register(col, new_objects[col])
|
||||||
|
|
||||||
# Maintains the frame and object with the highest score
|
# Maintains the frame and object with the highest score
|
||||||
class BestFrames(threading.Thread):
|
class BestFrames(threading.Thread):
|
||||||
|
Loading…
Reference in New Issue
Block a user