class_docstr: Implementation of the SMOT tracker
  The steps to use the tracker is:
  0. Set anchors from the SSD
  1. First call tracker.predict(new_frame)
  2. Then get the tracking anchor information
  3. Run the detractor with the tracking anchor information
  4. Run tracker.update(new_detection, track_info).
class_docstr_tok: ["Implementation","of","the","SMOT","tracker","The","steps","to","use","the","tracker","is",":","0",".","Set","anchors","from","the","SSD","1",".","First","call","tracker.predict","(","new_frame",")","2",".","Then","get","the","tracking","anchor","information","3",".","Run","the","detractor","with","the","tracking","anchor","information","4",".","Run","tracker.update","(","new_detection",",","track_info",")","."]
docstr: Update the tracks according to tracking and detection predictions.
  Parameters
  ----------
  new_detections: Nx5 ndarray
  tracking_predictions: Mx5 ndarray
  extra_info: a dictionary with extra information
  
  Returns
  -------
docstr_tok: ["Update","the","tracks","according","to","tracking","and","detection","predictions",".","Parameters","--","--","--","--","--","new_detections",":","Nx5","ndarray","tracking_predictions",":","Mx5","ndarray","extra_info",":","a","dictionary","with","extra","information","Returns","--","--","--","-"]
code: def update(
      self,
      new_detections: np.ndarray,
      tracking_predictions: np.ndarray,
      detection_anchor_indices: np.ndarray,
      tracking_anchor_indices: np.ndarray,
      tracking_anchor_weights: np.ndarray,
      tracking_classes: np.ndarray,
      extra_info: dict = None,
  ):
      """
      Update the tracks according to tracking and detection predictions.
      Parameters
      ----------
      new_detections: Nx5 ndarray
      tracking_predictions: Mx5 ndarray
      extra_info: a dictionary with extra information
  
      Returns
      -------
      """
      # pylint: disable=too-many-nested-blocks
      t_pose_processing = time.time()
  
      logging.info(
          "tracking predictions 's shape is {}".format(
              tracking_predictions.shape
          )
      )
      logging.debug(tracking_predictions)
      logging.debug(self.waiting_update_tracks)
  
      detection_landmarks = (
          extra_info["detection_landmarks"]
          if "detection_landmarks" in extra_info
          else None
      )
      tracking_landmarks = (
          extra_info["tracking_landmarks"]
          if "tracking_landmarks" in extra_info
          else None
      )
  
      for t in self.tracks:
          t.predict()
  
      # STEP 1: track level NMS
      still_active_track_pred_indices = []
      still_active_track_indices = []
  
      if len(tracking_predictions) > 0:
          # class wise NMS
          keep_set = set()
          for c in set(tracking_classes.ravel().tolist()):
              class_pick = np.nonzero(tracking_classes == c)[0]
              keep_tracking_pred_nms_indices = nms_fallback(
                  tracking_predictions[class_pick, ...],
                  self.track_nms_thresh,
              )
              for i_keep in keep_tracking_pred_nms_indices:
                  keep_set.add(class_pick[i_keep])
  
          still_active_track_pred_indices = []
          for i_pred, i_track in enumerate(self.waiting_update_tracks):
              if i_pred in keep_set:
                  self.tracks[i_track].update(
                      tracking_predictions[i_pred, :],
                      (
                          tracking_anchor_indices[i_pred, :],
                          tracking_anchor_weights[i_pred, :],
                      ),
                      tracking_landmarks[i_pred, :]
                      if tracking_landmarks is not None
                      else None,
                  )
              else:
                  # suppressed tracks in the track NMS process will be marked as Missing
                  self.tracks[i_track].mark_missed()
  
              if self.tracks[i_track].is_active():
                  still_active_track_pred_indices.append(i_pred)
                  still_active_track_indices.append(i_track)
  
      # STEP 2: Remove New Detection Overlapping with Tracks
      if (
          len(still_active_track_pred_indices) > 0
          and len(new_detections) > 0
      ):
          active_tracking_predictions = tracking_predictions[
              still_active_track_pred_indices, :
          ]
          det_track_max_iou = bbox_iou(
              new_detections[:, :4], active_tracking_predictions[:, :4]
          )
          same_class = new_detections[:, -1:] == (
              tracking_classes[still_active_track_pred_indices, :].T
          )
          # suppress all new detections that have high IOU with active tracks
          affinity = (det_track_max_iou * same_class).max(axis=1)
          keep_detection_indices = np.nonzero(
              affinity <= self.new_track_iou_thresh
          )[0]
      else:
          # otherwise simply keep all detections
          keep_detection_indices = list(range(len(new_detections)))
          active_tracking_predictions = np.array([])
  
      # STEP 3: New Track Initialization
      if len(keep_detection_indices) > 0:
          active_new_detections = new_detections[
              keep_detection_indices, :
          ]
          # (Optional) STEP 3.a: Perform joint linking of body and head
          if self.joint_linking:
              tracking_classes = np.array(tracking_classes)
              body2face_link, face2body_link = self._link_face_body(
                  active_new_detections,
                  extra_info["detection_keypoints"][
                      keep_detection_indices
                  ],
                  active_tracking_predictions,
                  extra_info["tracking_keypoints"][
                      still_active_track_pred_indices
                  ],
                  tracking_classes[still_active_track_pred_indices],
              )
          else:
              body2face_link, face2body_link = None, None
  
          new_tracks = []
          for idx, i_new_track in enumerate(keep_detection_indices):
              new_track = Track(
                  new_detections[i_new_track, :4],
                  self.all_track_id,
                  (
                      detection_anchor_indices[i_new_track, :],
                      np.array([1]),
                  ),
                  keep_alive_thresh=self.keep_alive,
                  class_id=new_detections[i_new_track, -1],
                  attributes=detection_landmarks[i_new_track, :]
                  if detection_landmarks is not None
                  else None,
              )
              if self.joint_linking:
                  if new_track.class_id == 0:
                      # new face track
                      if idx in face2body_link[0]:
                          logging.debug(idx, i_new_track, "0")
                          body_idx = face2body_link[0][idx]
                          if idx > body_idx:
                              new_track.link_to(new_tracks[body_idx])
                      elif idx in face2body_link[2]:
                          logging.debug(idx, i_new_track, "1")
                          body_idx = face2body_link[2][idx]
                          new_track.link_to(
                              self.tracks[
                                  still_active_track_indices[body_idx]
                              ]
                          )
  
                  if new_track.class_id == 1:
                      # new body track
                      if idx in body2face_link[0]:
                          face_idx = body2face_link[0][idx]
                          if idx > face_idx:
                              new_track.link_to(new_tracks[face_idx])
                      elif idx in body2face_link[2]:
                          face_idx = body2face_link[2][idx]
                          new_track.link_to(
                              self.tracks[
                                  still_active_track_indices[face_idx]
                              ]
                          )
  
              self.all_track_id += 1
              self.tracks.append(new_track)
              new_tracks.append(new_track)
  
      elapsed_post_processing = time.time() - t_pose_processing
      logging.info(
          "total tracklets to now is {}, post-processing time: {:.05f} sec".format(
              self.all_track_id, elapsed_post_processing
          )
      )
  
imports: from __future__ import absolute_import
  import logging
  import time
  import numpy
  import mxnet
  from gluoncv.utils.bbox import bbox_iou
  from gluoncv.data import COCODetection
  from .utils import timeit, Track
  from .motion_estimation import FarneBeckFlowMotionEstimator
  from .motion_estimation import DummyMotionEstimator
label_desc: Use image node_id 5 for calling the SMOTTracker obj's underlying member method code with example usage: obj.update(new_detections, tracking_predictions, detection_anchor_indices, tracking_anchor_indices, tracking_anchor_weights, tracking_classes, extra_info) without return types