Example #1
0
class ReIDTracker(Tracker):
    """
    Specialized tracker class which inherits from the basic Tracker class
    Utilizes the KalmanFilter and a person re-identification neural network for more accurate bounding box associations
    """
    def __init__(self, matching_threshold=0.2, diff_threshold=0.2):
        """ Initialize the tracker from base class with relevant metrics """
        Tracker.__init__(self, matching_threshold=matching_threshold)
        self.metric_nn = Metric('ReIDNN')
        self.metric_iou = Metric('iou')
        self.diff_threshold = diff_threshold

    def update(self, frame, detections):
        """
        Core method of the tracker, updates tracked objects after receiving detections.
        Associates detection with existing tracked objects, deletes disappeared detection and creates
        new trackers if non are associated with detections.
        :param frame: (array) np.ndarray representing image frame associated with current detections
        :param detections: (array) list of detections (bounding boxes in [x1,x2,y1,y2] format)
        :return (array) list of tracked objects tuples in format (ID, [x1,x2,y1,y2])
        """
        # Check to see if there are no detections and handle if so
        if len(detections) == 0:
            return self.handle_no_detections()

        # if we are currently not tracking any objects, register all detections to new tracks
        if len(self.tracked) == 0:
            for i in range(0, len(detections)):
                self.register(detections[i])

        # otherwise, check to see how the new detections relate to current tracks
        else:
            self.associate(frame, detections)

        # return the corrected estimate of tracked objects and their unique ids
        return self.project()

    def associate(self, frame, detections):
        """
        Performs the Hungarian algorithm and assignment between detections and existing
        trackers according to distance matrix and metric specified.
        updates the Tracker class dictionaries after associations
        :param frame: (array) np.ndarray representing image frame associated with current detections
        :param detections: (array) list of new detections
         """
        # Grab the set of object IDs and corresponding states
        track_ids = list(self.tracked.keys())

        # Get predicted tracked object states from Kalman Filter
        tracked_states = [track.predict() for track in self.tracked.values()]

        # Crop the image from each bounding box associated to new detections and current tracks
        tracked_crops = Tracker.crop_bbox_from_frame(frame, tracked_states)
        detections_crops = Tracker.crop_bbox_from_frame(frame, detections)

        # Compute the distance matrix between detections and trackers according to metric
        D = self.metric_iou.distance_matrix(tracked_states, detections)
        D_iou_sorted = -np.sort(-D)

        # Check if there are difficult overlapping IoU between a track and several detections
        for row_idx in xrange(D.shape[0]):
            if (D_iou_sorted[row_idx, 0] - D_iou_sorted[row_idx, 1] <
                    self.diff_threshold) and (D_iou_sorted[row_idx, 0] >
                                              self.matching_threshold):
                # Consult with re-identification network
                D_nn = self.metric_nn.distance_matrix(tracked_crops,
                                                      detections_crops)
                D = np.multiply(D, D_nn)
                break

        # Associate detections to existing trackers according to distance matrix
        self.linear_assignment(D, track_ids, detections)
Example #2
0
class ORBTracker(Tracker):
    """
    Specialized tracker class which inherits from the basic Tracker class
    Utilizes the KalmanFilter and feature matching (ORB) for more accurate bounding box associations
    """
    def __init__(self, matching_threshold=0.01):
        """ Initialize the tracker from base class with relevant metrics """
        Tracker.__init__(self, matching_threshold)
        self.metric_orb = Metric('ORB')
        self.metric_iou = Metric('iou')

    def update(self, frame, detections):
        """
        Core method of the tracker, updates tracked objects after receiving detections.
        Associates detection with existing tracked objects, deletes disappeared detection and creates
        new trackers if non are associated with detections.
        :param frame: (array) np.ndarray representing image frame associated with current detections
        :param detections: (array) list of detections (bounding boxes in [x1,x2,y1,y2] format)
        :return (array) list of tracked objects tuples in format (ID, [x1,x2,y1,y2])
        """
        # Check to see if there are no detections and handle if so
        if len(detections) == 0:
            return self.handle_no_detections()

        # if we are currently not tracking any objects, register all detections to new tracks
        if len(self.tracked) == 0:
            for i in range(0, len(detections)):
                self.register(detections[i])

        # otherwise, check to see how the new detections relate to current tracks
        else:
            self.associate(frame, detections)

        # return the corrected estimate of tracked objects and their unique ids
        return self.project()

    def associate(self, frame, detections):
        """
        Performs the Hungarian algorithm and assignment between detections and existing
        trackers according to distance matrix and metric specified.
        updates the Tracker class dictionaries after associations
        :param frame: (array) np.ndarray representing image frame associated with current detections
        :param detections: (array) list of new detections
         """
        # Grab the set of object IDs and corresponding states
        track_ids = list(self.tracked.keys())

        # Get predicted tracked object states from Kalman Filter
        tracked_states = [track.predict() for track in self.tracked.values()]

        # Crop the image from each bounding box associated to new detections and current tracks
        tracked_crops = Tracker.crop_bbox_from_frame(frame, tracked_states)
        detections_crops = Tracker.crop_bbox_from_frame(frame, detections)

        # Compute the distance matrix between detections and trackers according to metric
        D_orb = self.metric_orb.distance_matrix(tracked_crops,
                                                detections_crops)
        D_iou = self.metric_iou.distance_matrix(tracked_states, detections)
        w = 0.2
        D = np.multiply(w * D_orb, (1 - w) * D_iou)

        # Associate detections to existing trackers according to distance matrix
        self.linear_assignment(D, track_ids, detections)