class_docstr: OCSORT tracker, support single class
  
  Args:
      det_thresh (float): threshold of detection score
      max_age (int): maximum number of missed misses before a track is deleted
      min_hits (int): minimum hits for associate
      iou_threshold (float): iou threshold for associate
      delta_t (int): delta_t of previous observation
      inertia (float): vdc_weight of angle_diff_cost for associate
      vertical_ratio (float): w/h, the vertical ratio of the bbox to filter
          bad results. If set <= 0 means no need to filter bboxes，usually set
          1.6 for pedestrian tracking.
      min_box_area (int): min box area to filter out low quality boxes
      use_byte (bool): Whether use ByteTracker, default False
class_docstr_tok: ["OCSORT","tracker",",","support","single","class","Args",":","det_thresh","(","float",")",":","threshold","of","detection","score","max_age","(","int",")",":","maximum","number","of","missed","misses","before","a","track","is","deleted","min_hits","(","int",")",":","minimum","hits","for","associate","iou_threshold","(","float",")",":","iou","threshold","for","associate","delta_t","(","int",")",":","delta_t","of","previous","observation","inertia","(","float",")",":","vdc_weight","of","angle_diff_cost","for","associate","vertical_ratio","(","float",")",":","w\/h",",","the","vertical","ratio","of","the","bbox","to","filter","bad","results",".","If","set","<","=","0","means","no","need","to","filter","bboxes\uff0cusually","set","1.6","for","pedestrian","tracking",".","min_box_area","(","int",")",":","min","box","area","to","filter","out","low","quality","boxes","use_byte","(","bool",")",":","Whether","use","ByteTracker",",","default","False"]
docstr: Args:
      pred_dets (np.array): Detection results of the image, the shape is
          [N, 6], means 'cls_id, score, x0, y0, x1, y1'.
      pred_embs (np.array): Embedding results of the image, the shape is
          [N, 128] or [N, 512], default as None.
  
  Return:
      tracking boxes (np.array): [M, 6], means 'x0, y0, x1, y1, score, id'.
docstr_tok: ["Args",":","pred_dets","(","np.array",")",":","Detection","results","of","the","image",",","the","shape","is","[","N",",","6","]",",","means","'cls_id",",","score",",","x0",",","y0",",","x1",",","y1","'",".","pred_embs","(","np.array",")",":","Embedding","results","of","the","image",",","the","shape","is","[","N",",","128","]","or","[","N",",","512","]",",","default","as","None",".","Return",":","tracking","boxes","(","np.array",")",":","[","M",",","6","]",",","means","'x0",",","y0",",","x1",",","y1",",","score",",","id","'","."]
code: def update(self, pred_dets, pred_embs=None):
      """
      Args:
          pred_dets (np.array): Detection results of the image, the shape is
              [N, 6], means 'cls_id, score, x0, y0, x1, y1'.
          pred_embs (np.array): Embedding results of the image, the shape is
              [N, 128] or [N, 512], default as None.
  
      Return:
          tracking boxes (np.array): [M, 6], means 'x0, y0, x1, y1, score, id'.
      """
      if pred_dets is None:
          return np.empty((0, 6))
  
      self.frame_count += 1
  
      bboxes = pred_dets[:, 2:]
      scores = pred_dets[:, 1:2]
      dets = np.concatenate((bboxes, scores), axis=1)
      scores = scores.squeeze(-1)
  
      inds_low = scores > 0.1
      inds_high = scores < self.det_thresh
      inds_second = np.logical_and(inds_low, inds_high)
      # self.det_thresh > score > 0.1, for second matching
      dets_second = dets[inds_second]  # detections for second matching
      remain_inds = scores > self.det_thresh
      dets = dets[remain_inds]
  
      # get predicted locations from existing trackers.
      trks = np.zeros((len(self.trackers), 5))
      to_del = []
      ret = []
      for t, trk in enumerate(trks):
          pos = self.trackers[t].predict()[0]
          trk[:] = [pos[0], pos[1], pos[2], pos[3], 0]
          if np.any(np.isnan(pos)):
              to_del.append(t)
      trks = np.ma.compress_rows(np.ma.masked_invalid(trks))
      for t in reversed(to_del):
          self.trackers.pop(t)
  
      if self.use_angle_cost:
          velocities = np.array(
              [
                  trk.velocity
                  if trk.velocity is not None
                  else np.array((0, 0))
                  for trk in self.trackers
              ]
          )
  
          k_observations = np.array(
              [
                  k_previous_obs(
                      trk.observations, trk.age, self.delta_t
                  )
                  for trk in self.trackers
              ]
          )
      last_boxes = np.array(
          [trk.last_observation for trk in self.trackers]
      )
      """
              First round of association
          """
      if self.use_angle_cost:
          matched, unmatched_dets, unmatched_trks = associate(
              dets,
              trks,
              self.iou_threshold,
              velocities,
              k_observations,
              self.inertia,
          )
      else:
          matched, unmatched_dets, unmatched_trks = associate_only_iou(
              dets, trks, self.iou_threshold
          )
  
      for m in matched:
          self.trackers[m[1]].update(
              dets[m[0], :], angle_cost=self.use_angle_cost
          )
      """
              Second round of associaton by OCR
          """
      # BYTE association
      if (
          self.use_byte
          and len(dets_second) > 0
          and unmatched_trks.shape[0] > 0
      ):
          u_trks = trks[unmatched_trks]
          iou_left = iou_batch(
              dets_second, u_trks
          )  # iou between low score detections and unmatched tracks
          iou_left = np.array(iou_left)
          if iou_left.max() > self.iou_threshold:
              """
              NOTE: by using a lower threshold, e.g., self.iou_threshold - 0.1, you may
              get a higher performance especially on MOT17/MOT20 datasets. But we keep it
              uniform here for simplicity
              """
              matched_indices = linear_assignment(-iou_left)
              to_remove_trk_indices = []
              for m in matched_indices:
                  det_ind, trk_ind = m[0], unmatched_trks[m[1]]
                  if iou_left[m[0], m[1]] < self.iou_threshold:
                      continue
                  self.trackers[trk_ind].update(
                      dets_second[det_ind, :],
                      angle_cost=self.use_angle_cost,
                  )
                  to_remove_trk_indices.append(trk_ind)
              unmatched_trks = np.setdiff1d(
                  unmatched_trks, np.array(to_remove_trk_indices)
              )
  
      if unmatched_dets.shape[0] > 0 and unmatched_trks.shape[0] > 0:
          left_dets = dets[unmatched_dets]
          left_trks = last_boxes[unmatched_trks]
          iou_left = iou_batch(left_dets, left_trks)
          iou_left = np.array(iou_left)
          if iou_left.max() > self.iou_threshold:
              """
              NOTE: by using a lower threshold, e.g., self.iou_threshold - 0.1, you may
              get a higher performance especially on MOT17/MOT20 datasets. But we keep it
              uniform here for simplicity
              """
              rematched_indices = linear_assignment(-iou_left)
              to_remove_det_indices = []
              to_remove_trk_indices = []
              for m in rematched_indices:
                  det_ind, trk_ind = (
                      unmatched_dets[m[0]],
                      unmatched_trks[m[1]],
                  )
                  if iou_left[m[0], m[1]] < self.iou_threshold:
                      continue
                  self.trackers[trk_ind].update(
                      dets[det_ind, :], angle_cost=self.use_angle_cost
                  )
                  to_remove_det_indices.append(det_ind)
                  to_remove_trk_indices.append(trk_ind)
              unmatched_dets = np.setdiff1d(
                  unmatched_dets, np.array(to_remove_det_indices)
              )
              unmatched_trks = np.setdiff1d(
                  unmatched_trks, np.array(to_remove_trk_indices)
              )
  
      for m in unmatched_trks:
          self.trackers[m].update(None)
  
      # create and initialise new trackers for unmatched detections
      for i in unmatched_dets:
          trk = KalmanBoxTracker(dets[i, :], delta_t=self.delta_t)
          self.trackers.append(trk)
  
      i = len(self.trackers)
      for trk in reversed(self.trackers):
          if trk.last_observation.sum() < 0:
              d = trk.get_state()[0]
          else:
              d = trk.last_observation  # tlbr + score
          if (trk.time_since_update < 1) and (
              trk.hit_streak >= self.min_hits
              or self.frame_count <= self.min_hits
          ):
              # +1 as MOT benchmark requires positive
              ret.append(
                  np.concatenate((d, [trk.id + 1])).reshape(1, -1)
              )
          i -= 1
          # remove dead tracklet
          if trk.time_since_update > self.max_age:
              self.trackers.pop(i)
      if len(ret) > 0:
          return np.concatenate(ret)
      return np.empty((0, 6))
  
file_path: PaddleDetection/ppdet/modeling/mot/tracker/ocsort_tracker.py
imports: import numpy
  from ..matching.ocsort_matching import associate, linear_assignment, iou_batch, associate_only_iou
  from ..motion.ocsort_kalman_filter import OCSORTKalmanFilter
  from ppdet.core.workspace import register, serializable
label_desc: Use image node_id 2 for calling the OCSORTTracker obj's underlying member method code with example usage: obj.update(pred_dets, pred_embs) and returns: np, np, np