diff --git a/src/centroid_tracker/centroidtracker.py b/src/centroid_tracker/centroidtracker.py index b965674..f8feada 100644 --- a/src/centroid_tracker/centroidtracker.py +++ b/src/centroid_tracker/centroidtracker.py @@ -3,151 +3,152 @@ from collections import OrderedDict import numpy as np + class CentroidTracker(): - def __init__(self, maxDisappeared=5): - # initialize the next unique object ID along with two ordered - # dictionaries used to keep track of mapping a given object - # ID to its centroid and number of consecutive frames it has - # been marked as "disappeared", respectively - self.nextObjectID = 0 - self.objects = OrderedDict() - self.disappeared = OrderedDict() - - # store the number of maximum consecutive frames a given - # object is allowed to be marked as "disappeared" until we - # need to deregister the object from tracking - self.maxDisappeared = maxDisappeared - - def register(self, centroid): - # when registering an object we use the next available object - # ID to store the centroid - self.objects[self.nextObjectID] = centroid - self.disappeared[self.nextObjectID] = 0 - self.nextObjectID += 1 - - def deregister(self, objectID): - # to deregister an object ID we delete the object ID from - # both of our respective dictionaries - del self.objects[objectID] - del self.disappeared[objectID] - - def update(self, rects): - # check to see if the list of input bounding box rectangles - # is empty - if len(rects) == 0: - # loop over any existing tracked objects and mark them - # as disappeared - for objectID in self.disappeared.keys(): - self.disappeared[objectID] += 1 - - # if we have reached a maximum number of consecutive - # frames where a given object has been marked as - # missing, deregister it - if self.disappeared[objectID] > self.maxDisappeared: - self.deregister(objectID) - - # return early as there are no centroids or tracking info - # to update - return self.objects - - # initialize an array of input centroids for the current frame - inputCentroids = np.zeros((len(rects), 2), dtype="int") - - # 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) - - # 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]) - - # 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()) - - # compute the distance between each pair of object - # centroids and input centroids, respectively -- our - # goal will be to match an input centroid to an existing - # object centroid - D = dist.cdist(np.array(objectCentroids), inputCentroids) - - # in order to perform this matching we must (1) find the - # 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 as at the *front* of the index - # list - rows = D.min(axis=1).argsort() - - # next, we perform a similar process on the columns by - # finding the smallest value in each column and then - # sorting using the previously computed row index list - cols = D.argmin(axis=1)[rows] - - # in order to determine if we need to update, register, - # or deregister an object we need to keep track of which - # of the rows and column indexes we have already examined - usedRows = set() - usedCols = set() - - # loop over the combination of the (row, column) index - # tuples - for (row, col) in zip(rows, cols): - # if we have already examined either the row or - # column value before, ignore it - # val - 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 = objectIDs[row] - self.objects[objectID] = inputCentroids[col] - 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]) - - # return the set of trackable objects - return self.objects + def __init__(self, maxDisappeared=30): + # initialize the next unique object ID along with two ordered + # dictionaries used to keep track of mapping a given object + # ID to its centroid and number of consecutive frames it has + # been marked as "disappeared", respectively + self.nextObjectID = 0 + self.objects = OrderedDict() + self.disappeared = OrderedDict() + + # store the number of maximum consecutive frames a given + # object is allowed to be marked as "disappeared" until we + # need to deregister the object from tracking + self.maxDisappeared = maxDisappeared + + def register(self, centroid): + # when registering an object we use the next available object + # ID to store the centroid + self.objects[self.nextObjectID] = centroid + self.disappeared[self.nextObjectID] = 0 + self.nextObjectID += 1 + + def deregister(self, objectID): + # to deregister an object ID we delete the object ID from + # both of our respective dictionaries + del self.objects[objectID] + del self.disappeared[objectID] + + def update(self, rects): + # check to see if the list of input bounding box rectangles + # is empty + if len(rects) == 0: + # loop over any existing tracked objects and mark them + # as disappeared + for objectID in self.disappeared.keys(): + self.disappeared[objectID] += 1 + + # if we have reached a maximum number of consecutive + # frames where a given object has been marked as + # missing, deregister it + if self.disappeared[objectID] > self.maxDisappeared: + self.deregister(objectID) + + # return early as there are no centroids or tracking info + # to update + return self.objects + + # initialize an array of input centroids for the current frame + inputCentroids = np.zeros((len(rects), 2), dtype="int") + + # 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) + + # 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]) + + # 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()) + + # compute the distance between each pair of object + # centroids and input centroids, respectively -- our + # goal will be to match an input centroid to an existing + # object centroid + D = dist.cdist(np.array(objectCentroids), inputCentroids) + + # in order to perform this matching we must (1) find the + # 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 as at the *front* of the index + # list + rows = D.min(axis=1).argsort() + + # next, we perform a similar process on the columns by + # finding the smallest value in each column and then + # sorting using the previously computed row index list + cols = D.argmin(axis=1)[rows] + + # in order to determine if we need to update, register, + # or deregister an object we need to keep track of which + # of the rows and column indexes we have already examined + usedRows = set() + usedCols = set() + + # loop over the combination of the (row, column) index + # tuples + for (row, col) in zip(rows, cols): + # if we have already examined either the row or + # column value before, ignore it + # val + 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 = objectIDs[row] + self.objects[objectID] = inputCentroids[col] + 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]) + + # return the set of trackable objects + return self.objects diff --git a/src/main.py b/src/main.py index a2ee06d..90f7e0a 100644 --- a/src/main.py +++ b/src/main.py @@ -3,11 +3,12 @@ import datetime from shutil import copyfile -import video_to_frames +import video_to_frames_no_skipping from frame_seperater import FrameSeperator import create_shot_boundaries import objects_identifier_of_frames import summary_from_frames_with_obj +import frames_to_video def run(): @@ -31,7 +32,7 @@ def run(): print('Error: Creating directory of data') # video broken to frames - video_to_frames.get_frames(original_video_location, location_to_store_all_frames) + video_to_frames_no_skipping.get_frames(original_video_location, location_to_store_all_frames) # shot boundaries are identified shot_boundaries = create_shot_boundaries.run(location_to_store_all_frames) @@ -77,6 +78,15 @@ def run(): print( "\n**************** Keyframes moved to the ./test_data/generated_summary_keyframes/ location ****************") + + output_video_path = "./test_data/output_video/" + output_video_name = "output_video.avi" + fps = 8.0 + frames_to_video.convert_frames_to_video(location_to_store_summary_keyframes, output_video_path, output_video_name, fps) + + print( + "\n**************** summary video generated ./test_data/output_video/ location ****************") + elapsed_time = datetime.datetime.now() - t1 print("elapsed time is " + str(elapsed_time)) diff --git a/src/net/netarch.py b/src/net/netarch.py index 3d0b44e..c12c0a7 100644 --- a/src/net/netarch.py +++ b/src/net/netarch.py @@ -48,14 +48,17 @@ def predict(self, image): output = self._inf_model.predict(image)[0] if output.size == 0: - list1 = [] - return list1 + return [], [] boxes = output[:, :4] label_idxs = output[:,5].astype(int) labels = [YoloParams.CLASS_LABELS[l] for l in label_idxs] + # if (boxes is None) and (labels is None): + # boxes = [] + # labels = [] + return boxes, labels diff --git a/src/summary_from_frames_with_obj.py b/src/summary_from_frames_with_obj.py index f91c6d3..bc62c32 100644 --- a/src/summary_from_frames_with_obj.py +++ b/src/summary_from_frames_with_obj.py @@ -15,7 +15,7 @@ def summary_from_frames_with_obj(frame_dic_with_objects): elif set(frames_with_max_obj[obj_frame_index]).issubset(set(frame)): if frames_with_max_obj[obj_frame_index] not in redundant_frames: redundant_frames.append(frames_with_max_obj[obj_frame_index]) - break + if new_obj: frames_with_max_obj.append(frame) @@ -24,16 +24,14 @@ def summary_from_frames_with_obj(frame_dic_with_objects): if frame_name not in summary_frames: summary_frames.append(frame_name) - # for index in range(len(frames_with_max_obj) - 1): - # for j in range(index + 1, len(frames_with_max_obj)): - # if set(frames_with_max_obj[index]).issubset(set(frames_with_max_obj[j])): - # redundant_frames.append(index) - for obj_set in redundant_frames: redundant_index = frames_with_max_obj.index(obj_set) frames_with_max_obj.pop(redundant_index) summary_frames.pop(redundant_index) + for i in frames_with_max_obj: + print(i) + return summary_frames