Improve handling of object matching

Use `np.unique` to determine the correct set of row/col pairs to iterate
over when doing the object matching without needing to track which rows
or columns have already been seen.  Add to some of the accompanying
documentation to clarify this algorithm.

Also fix what looks to be an erroneous early return, and change this to
a continue.
This commit is contained in:
Sean Vig 2021-05-21 22:11:36 -04:00 committed by Blake Blackshear
parent 57864f2be6
commit 80f8256422

View File

@ -82,56 +82,45 @@ class ObjectTracker:
if len(current_objects) == 0: if len(current_objects) == 0:
for index, obj in enumerate(group): for index, obj in enumerate(group):
self.register(index, obj) self.register(index, obj)
return continue
new_centroids = np.array([o["centroid"] for o in group]) new_centroids = np.array([o["centroid"] for o in group])
# compute the distance between each pair of tracked # compute the distance between each pair of tracked
# centroids and new centroids, respectively -- our # centroids and new centroids, respectively -- our
# goal will be to match each new centroid to an existing # goal will be to match each current centroid to a new
# object centroid # object centroid
D = dist.cdist(current_centroids, new_centroids) D = dist.cdist(current_centroids, new_centroids)
# in order to perform this matching we must (1) find the # in order to perform this matching we must (1) find the smallest
# smallest value in each row and then (2) sort the row # value in each row (i.e. the distance from each current object to
# indexes based on their minimum values so that the row # the closest new object) and then (2) sort the row indexes based
# with the smallest value is at the *front* of the index # on their minimum values so that the row with the smallest
# list # distance (the best match) is at the *front* of the index list
rows = D.min(axis=1).argsort() rows = D.min(axis=1).argsort()
# next, we perform a similar process on the columns by # next, we determine which new object each existing object matched
# finding the smallest value in each column and then # against, and apply the same sorting as was applied previously
# sorting using the previously computed row index list
cols = D.argmin(axis=1)[rows] cols = D.argmin(axis=1)[rows]
# in order to determine if we need to update, register, # many current objects may register with each new object, so only
# or deregister an object we need to keep track of which # match the closest ones. unique returns the indices of the first
# of the rows and column indexes we have already examined # occurrences of each value, and because the rows are sorted by
usedRows = set() # distance, this will be index of the closest match
usedCols = set() _, index = np.unique(cols, return_index=True)
rows = rows[index]
cols = cols[index]
# loop over the combination of the (row, column) index # loop over the combination of the (row, column) index tuples
# tuples for row, col in zip(rows, cols):
for (row, col) in zip(rows, cols): # grab the object ID for the current row, set its new centroid,
# if we have already examined either the row or # and reset the disappeared counter
# column value before, ignore it
if row in usedRows or col in usedCols:
continue
# otherwise, grab the object ID for the current row,
# set its new centroid, and reset the disappeared
# counter
objectID = current_ids[row] objectID = current_ids[row]
self.update(objectID, group[col]) self.update(objectID, group[col])
# indicate that we have examined each of the row and # compute the row and column indices we have NOT yet examined
# column indexes, respectively unusedRows = set(range(D.shape[0])).difference(rows)
usedRows.add(row) unusedCols = set(range(D.shape[1])).difference(cols)
usedCols.add(col)
# compute the column index we have NOT yet examined
unusedRows = set(range(0, D.shape[0])).difference(usedRows)
unusedCols = set(range(0, D.shape[1])).difference(usedCols)
# in the event that the number of object centroids is # in the event that the number of object centroids is
# equal or greater than the number of input centroids # equal or greater than the number of input centroids