class_docstr: Tracker for ByteTrack.
  
  Args:
      motion (dict): Configuration of motion. Defaults to None.
      obj_score_thrs (dict): Detection score threshold for matching objects.
          - high (float): Threshold of the first matching. Defaults to 0.6.
          - low (float): Threshold of the second matching. Defaults to 0.1.
      init_track_thr (float): Detection score threshold for initializing a
          new tracklet. Defaults to 0.7.
      weight_iou_with_det_scores (bool): Whether using detection scores to
          weight IOU which is used for matching. Defaults to True.
      match_iou_thrs (dict): IOU distance threshold for matching between two
          frames.
          - high (float): Threshold of the first matching. Defaults to 0.1.
          - low (float): Threshold of the second matching. Defaults to 0.5.
          - tentative (float): Threshold of the matching for tentative
              tracklets. Defaults to 0.3.
      num_tentatives (int, optional): Number of continuous frames to confirm
          a track. Defaults to 3.
class_docstr_tok: ["Tracker","for","ByteTrack",".","Args",":","motion","(","dict",")",":","Configuration","of","motion",".","Defaults","to","None",".","obj_score_thrs","(","dict",")",":","Detection","score","threshold","for","matching","objects",".","-","high","(","float",")",":","Threshold","of","the","first","matching",".","Defaults","to","0.6",".","-","low","(","float",")",":","Threshold","of","the","second","matching",".","Defaults","to","0.1.","init_track_thr","(","float",")",":","Detection","score","threshold","for","initializing","a","new","tracklet",".","Defaults","to","0.7.","weight_iou_with_det_scores","(","bool",")",":","Whether","using","detection","scores","to","weight","IOU","which","is","used","for","matching",".","Defaults","to","True",".","match_iou_thrs","(","dict",")",":","IOU","distance","threshold","for","matching","between","two","frames",".","-","high","(","float",")",":","Threshold","of","the","first","matching",".","Defaults","to","0.1",".","-","low","(","float",")",":","Threshold","of","the","second","matching",".","Defaults","to","0.5",".","-","tentative","(","float",")",":","Threshold","of","the","matching","for","tentative","tracklets",".","Defaults","to","0.3.","num_tentatives","(","int",",","optional",")",":","Number","of","continuous","frames","to","confirm","a","track",".","Defaults","to","3","."]
docstr: Tracking forward function.
  
  Args:
      data_sample (:obj:`DetDataSample`): The data sample.
          It includes information such as `pred_instances`.
  
  Returns:
      :obj:`InstanceData`: Tracking results of the input images.
      Each InstanceData usually contains ``bboxes``, ``labels``,
      ``scores`` and ``instances_id``.
docstr_tok: ["Tracking","forward","function",".","Args",":","data_sample","(",":","obj",":","`","DetDataSample","`",")",":","The","data","sample",".","It","includes","information","such","as","`","pred_instances","`",".","Returns",":",":","obj",":","`","InstanceData","`",":","Tracking","results","of","the","input","images",".","Each","InstanceData","usually","contains","``","bboxes","``",",","``","labels","``",",","``","scores","``","and","``","instances_id","``","."]
code: def track(self, data_sample: DetDataSample, **kwargs) -> InstanceData:
      """Tracking forward function.
  
      Args:
          data_sample (:obj:`DetDataSample`): The data sample.
              It includes information such as `pred_instances`.
  
      Returns:
          :obj:`InstanceData`: Tracking results of the input images.
          Each InstanceData usually contains ``bboxes``, ``labels``,
          ``scores`` and ``instances_id``.
      """
      metainfo = data_sample.metainfo
      bboxes = data_sample.pred_instances.bboxes
      labels = data_sample.pred_instances.labels
      scores = data_sample.pred_instances.scores
  
      frame_id = metainfo.get("frame_id", -1)
      if frame_id == 0:
          self.reset()
      if not hasattr(self, "kf"):
          self.kf = self.motion
  
      if self.empty or bboxes.size(0) == 0:
          valid_inds = scores > self.init_track_thr
          scores = scores[valid_inds]
          bboxes = bboxes[valid_inds]
          labels = labels[valid_inds]
          num_new_tracks = bboxes.size(0)
          ids = torch.arange(
              self.num_tracks, self.num_tracks + num_new_tracks
          ).to(labels)
          self.num_tracks += num_new_tracks
  
      else:
          # 0. init
          ids = torch.full(
              (bboxes.size(0),),
              -1,
              dtype=labels.dtype,
              device=labels.device,
          )
  
          # get the detection bboxes for the first association
          first_det_inds = scores > self.obj_score_thrs["high"]
          first_det_bboxes = bboxes[first_det_inds]
          first_det_labels = labels[first_det_inds]
          first_det_scores = scores[first_det_inds]
          first_det_ids = ids[first_det_inds]
  
          # get the detection bboxes for the second association
          second_det_inds = (~first_det_inds) & (
              scores > self.obj_score_thrs["low"]
          )
          second_det_bboxes = bboxes[second_det_inds]
          second_det_labels = labels[second_det_inds]
          second_det_scores = scores[second_det_inds]
          second_det_ids = ids[second_det_inds]
  
          # 1. use Kalman Filter to predict current location
          for id in self.confirmed_ids:
              # track is lost in previous frame
              if self.tracks[id].frame_ids[-1] != frame_id - 1:
                  self.tracks[id].mean[7] = 0
              (
                  self.tracks[id].mean,
                  self.tracks[id].covariance,
              ) = self.kf.predict(
                  self.tracks[id].mean, self.tracks[id].covariance
              )
  
          # 2. first match
          (
              first_match_track_inds,
              first_match_det_inds,
          ) = self.assign_ids(
              self.confirmed_ids,
              first_det_bboxes,
              first_det_labels,
              first_det_scores,
              self.weight_iou_with_det_scores,
              self.match_iou_thrs["high"],
          )
          # '-1' mean a detection box is not matched with tracklets in
          # previous frame
          valid = first_match_det_inds > -1
          first_det_ids[valid] = torch.tensor(self.confirmed_ids)[
              first_match_det_inds[valid]
          ].to(labels)
  
          first_match_det_bboxes = first_det_bboxes[valid]
          first_match_det_labels = first_det_labels[valid]
          first_match_det_scores = first_det_scores[valid]
          first_match_det_ids = first_det_ids[valid]
          assert (first_match_det_ids > -1).all()
  
          first_unmatch_det_bboxes = first_det_bboxes[~valid]
          first_unmatch_det_labels = first_det_labels[~valid]
          first_unmatch_det_scores = first_det_scores[~valid]
          first_unmatch_det_ids = first_det_ids[~valid]
          assert (first_unmatch_det_ids == -1).all()
  
          # 3. use unmatched detection bboxes from the first match to match
          # the unconfirmed tracks
          (
              tentative_match_track_inds,
              tentative_match_det_inds,
          ) = self.assign_ids(
              self.unconfirmed_ids,
              first_unmatch_det_bboxes,
              first_unmatch_det_labels,
              first_unmatch_det_scores,
              self.weight_iou_with_det_scores,
              self.match_iou_thrs["tentative"],
          )
          valid = tentative_match_det_inds > -1
          first_unmatch_det_ids[valid] = torch.tensor(
              self.unconfirmed_ids
          )[tentative_match_det_inds[valid]].to(labels)
  
          # 4. second match for unmatched tracks from the first match
          first_unmatch_track_ids = []
          for i, id in enumerate(self.confirmed_ids):
              # tracklet is not matched in the first match
              case_1 = first_match_track_inds[i] == -1
              # tracklet is not lost in the previous frame
              case_2 = self.tracks[id].frame_ids[-1] == frame_id - 1
              if case_1 and case_2:
                  first_unmatch_track_ids.append(id)
  
          (
              second_match_track_inds,
              second_match_det_inds,
          ) = self.assign_ids(
              first_unmatch_track_ids,
              second_det_bboxes,
              second_det_labels,
              second_det_scores,
              False,
              self.match_iou_thrs["low"],
          )
          valid = second_match_det_inds > -1
          second_det_ids[valid] = torch.tensor(first_unmatch_track_ids)[
              second_match_det_inds[valid]
          ].to(ids)
  
          # 5. gather all matched detection bboxes from step 2-4
          # we only keep matched detection bboxes in second match, which
          # means the id != -1
          valid = second_det_ids > -1
          bboxes = torch.cat(
              (first_match_det_bboxes, first_unmatch_det_bboxes), dim=0
          )
          bboxes = torch.cat((bboxes, second_det_bboxes[valid]), dim=0)
  
          labels = torch.cat(
              (first_match_det_labels, first_unmatch_det_labels), dim=0
          )
          labels = torch.cat((labels, second_det_labels[valid]), dim=0)
  
          scores = torch.cat(
              (first_match_det_scores, first_unmatch_det_scores), dim=0
          )
          scores = torch.cat((scores, second_det_scores[valid]), dim=0)
  
          ids = torch.cat(
              (first_match_det_ids, first_unmatch_det_ids), dim=0
          )
          ids = torch.cat((ids, second_det_ids[valid]), dim=0)
  
          # 6. assign new ids
          new_track_inds = ids == -1
          ids[new_track_inds] = torch.arange(
              self.num_tracks, self.num_tracks + new_track_inds.sum()
          ).to(labels)
          self.num_tracks += new_track_inds.sum()
  
      self.update(
          ids=ids,
          bboxes=bboxes,
          scores=scores,
          labels=labels,
          frame_ids=frame_id,
      )
  
      # update pred_track_instances
      pred_track_instances = InstanceData()
      pred_track_instances.bboxes = bboxes
      pred_track_instances.labels = labels
      pred_track_instances.scores = scores
      pred_track_instances.instances_id = ids
  
      return pred_track_instances
  
file_path: mmdetection/mmdet/models/trackers/byte_tracker.py
imports: from typing import List, Optional, Tuple
  import numpy
  import torch
  from mmengine.structures import InstanceData
  from mmdet.registry import MODELS, TASK_UTILS
  from mmdet.structures import DetDataSample
  from mmdet.structures.bbox import bbox_cxcyah_to_xyxy, bbox_overlaps, bbox_xyxy_to_cxcyah
  from .base_tracker import BaseTracker
label_desc: Use image node_id 8 for calling the ByteTracker obj's underlying member method code with example usage: obj.track(data_sample) and returns: pred_track_instances