|
def update(self, rects): |
|
|
|
if len(rects) == 0: |
|
|
|
for objectID in list(self.disappeared.keys()): |
|
self.disappeared[objectID] += 1 |
|
|
|
if self.disappeared[objectID] > self.maxDisappeared: |
|
self.deregister(objectID) |
|
|
|
return self.bbox |
|
|
|
|
|
inputCentroids = np.zeros((len(rects), 2), dtype="int") |
|
inputRects = [] |
|
# loop over the bounding box rectangles |
|
for (i, (startX, startY, endX, endY)) in enumerate(rects): |
|
# use the bounding box coordinates to derive the centroid |
|
cX = int((startX + endX) / 2.0) |
|
cY = int((startY + endY) / 2.0) |
|
inputCentroids[i] = (cX, cY) |
|
inputRects.append(rects[i]) |
|
|
|
# if we are currently not tracking any objects take the input |
|
# centroids and register each of them |
|
if len(self.objects) == 0: |
|
for i in range(0, len(inputCentroids)): |
|
self.register(inputCentroids[i], inputRects[i]) # CHANGE |
|
|
|
# otherwise, are are currently tracking objects so we need to |
|
# try to match the input centroids to existing object |
|
# centroids |
|
else: |
|
# grab the set of object IDs and corresponding centroids |
|
objectIDs = list(self.objects.keys()) |
|
objectCentroids = list(self.objects.values()) |
|
|
|
D = dist.cdist(np.array(objectCentroids), inputCentroids) |
|
|
|
rows = D.min(axis=1).argsort() |
|
|
|
cols = D.argmin(axis=1)[rows] |
|
|
|
|
|
usedRows = set() |
|
usedCols = set() |
|
|
|
for (row, col) in zip(rows, cols): |
|
# if we have already examined either the row or |
|
# column value before, ignore it |
|
if row in usedRows or col in usedCols: |
|
continue |
|
|
|
# if the distance between centroids is greater than |
|
# the maximum distance, do not associate the two |
|
# centroids to the same object |
|
if D[row, col] > self.maxDistance: |
|
continue |
|
|
|
# otherwise, grab the object ID for the current row, |
|
# set its new centroid, and reset the disappeared |
|
# counter |
|
objectID = objectIDs[row] |
|
self.objects[objectID] = inputCentroids[col] |
|
self.bbox[objectID] = inputRects[col] # CHANGE |
|
self.disappeared[objectID] = 0 |
|
|
|
# indicate that we have examined each of the row and |
|
# column indexes, respectively |
|
usedRows.add(row) |
|
usedCols.add(col) |
|
|
|
# compute both the row and 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 |
|
# 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 = objectIDs[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.maxDisappeared: |
|
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(inputCentroids[col], inputRects[col]) |
|
|
|
# return the set of trackable objects |
|
# return self.objects |
|
return self.bbox |