Conversation
…stead of track kf state
…trackers into feat/core/oc-sort-alex
| # OC-SORT | ||
|
|
||
| [](https://arxiv.org/abs/2203.14360) | ||
| [](https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/how-to-track-objects-with-sort-tracker.ipynb) |
There was a problem hiding this comment.
Remember to update it later for OC-SORT
There was a problem hiding this comment.
If you look at the current docs, for example the ByteTrack page, you will see badges removed from the top for now. https://trackers.roboflow.com/develop/trackers/bytetrack/
Instead, a Tutorials section appears on the main page, with links to Google Colab notebooks. https://trackers.roboflow.com/develop/
docs/trackers/core/ocsort/tracker.md
Outdated
| 1. Observation-Centre Re-Update (ORU): runs a predict-update loop with a 'virtual trajectory' | ||
| depending on the last observation and new observation when a track is re-activated after being lost. | ||
| 2. Observation-Centric Momentum (OCM): incorporate the direction consistency of tracks in the cost matrix for the association. | ||
| 3. Observation-centric Recovery (OCR): a second-stage association step between the last observation of unmatched tracks and the unmatched observations after the usual association. It attempts to recover tracks that were lost due to object stopping or short-term occlusion. Uses only IoU. |
There was a problem hiding this comment.
"Uses only IoIU" as a separate line?
There was a problem hiding this comment.
I think that is a problem of the visualization here maybe, because I see it in the same line
docs/trackers/core/ocsort/tracker.md
Outdated
|
|
||
| ## Overview | ||
|
|
||
| OC-SORT remains Simple, Online, and Real-Time ([SORT](../sort/tracker.md)) but improves robustness during occlusion and non-linear motion. |
There was a problem hiding this comment.
"remains... like SORT". Otherwise, it sounds confusing
| improving tracking through occlusions, but may increase the possibility | ||
| of ID switching for objects with similar appearance. | ||
| frame_rate (float): Frame rate of the video (frames per second). | ||
| Used to calculate the maximum time a track can be lost. |
There was a problem hiding this comment.
specify that we talk about the number of frames: for how many frames a track/tracked entity can be lost
There was a problem hiding this comment.
I didnt understand the comment, can you explain further?
| form [x1, y1, x2, y2]. | ||
| """ | ||
| for detection_idx in unmatched_detections: | ||
| new_tracker = OCSORTTracklet(detections.xyxy[detection_idx]) |
There was a problem hiding this comment.
This might be super confusing in the future. I would opt for creating a new track or new tracklet, not a new tracker.
There was a problem hiding this comment.
Looks like new traklet to me.
There was a problem hiding this comment.
yes, agree. this came from me basing the code on SORT
There was a problem hiding this comment.
also, one comment on this, sv.Detections have the attribute 'tracker_id', so we have this colliding term there as well.
| for t, tracklet in enumerate(tracklets): | ||
| if tracklet.previous_to_last_observation is None: # if there is no previous box | ||
| continue | ||
| # In case the track is lost we use the last known box |
There was a problem hiding this comment.
Is it by the original OC-SORT design? It might introduce some measurement noise and lead towards a drift.
There was a problem hiding this comment.
yes, if there is not enough information to calculate a direction then that component is 0
tstanczyk95
left a comment
There was a problem hiding this comment.
The implementation code looks overall good with a few remarks from my side. In any case, we will need to discuss it online to clarify some parts and design choices as well as ensure about the parameters.
| # OC-SORT | ||
|
|
||
| [](https://arxiv.org/abs/2203.14360) | ||
| [](https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/how-to-track-objects-with-sort-tracker.ipynb) |
There was a problem hiding this comment.
If you look at the current docs, for example the ByteTrack page, you will see badges removed from the top for now. https://trackers.roboflow.com/develop/trackers/bytetrack/
Instead, a Tutorials section appears on the main page, with links to Google Colab notebooks. https://trackers.roboflow.com/develop/
docs/trackers/core/ocsort/tracker.md
Outdated
| OC-SORT remains Simple, Online, and Real-Time ([SORT](../sort/tracker.md)) but improves robustness during occlusion and non-linear motion. | ||
| It recognizes limitations from SORT and the linear motion assumption of the Kalman filter, and adds three | ||
| mechanisms to enhance tracking: | ||
| 1. Observation-Centre Re-Update (ORU): runs a predict-update loop with a 'virtual trajectory' | ||
| depending on the last observation and new observation when a track is re-activated after being lost. | ||
| 2. Observation-Centric Momentum (OCM): incorporate the direction consistency of tracks in the cost matrix for the association. | ||
| 3. Observation-centric Recovery (OCR): a second-stage association step between the last observation of unmatched tracks and the unmatched observations after the usual association. It attempts to recover tracks that were lost due to object stopping or short-term occlusion. Uses only IoU. |
There was a problem hiding this comment.
Let’s keep the text simple, like in the ByteTrack docs. https://trackers.roboflow.com/develop/trackers/bytetrack/ No lists. A single paragraph of text.
| depending on the last observation and new observation when a track is re-activated after being lost. | ||
| 2. Observation-Centric Momentum (OCM): incorporate the direction consistency of tracks in the cost matrix for the association. | ||
| 3. Observation-centric Recovery (OCR): a second-stage association step between the last observation of unmatched tracks and the unmatched observations after the usual association. It attempts to recover tracks that were lost due to object stopping or short-term occlusion. Uses only IoU. | ||
|
|
There was a problem hiding this comment.
We should have Benchmarks section here.
| ## Examples | ||
|
|
||
| === "inference" | ||
|
|
||
| ```python hl_lines="2 5 12" | ||
| import supervision as sv | ||
| from trackers import OCSORTTracker | ||
| from inference import get_model | ||
|
|
||
| tracker = OCSORTTracker() | ||
| model = get_model(model_id="rfdetr-medium") | ||
| annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER) | ||
|
|
||
| def callback(frame, _): | ||
| result = model.infer(frame)[0] | ||
| detections = sv.Detections.from_inference(result) | ||
| detections = tracker.update(detections) | ||
| return annotator.annotate(frame, detections, labels=detections.tracker_id) | ||
|
|
||
| sv.process_video( | ||
| source_path="<INPUT_VIDEO_PATH>", | ||
| target_path="<OUTPUT_VIDEO_PATH>", | ||
| callback=callback, | ||
| ) | ||
| ``` | ||
|
|
||
| === "rf-detr" | ||
|
|
||
| ```python hl_lines="2 5 11" | ||
| import supervision as sv | ||
| from trackers import OCSORTTracker | ||
| from rfdetr import RFDETRMedium | ||
|
|
||
| tracker = OCSORTTracker() | ||
| model = RFDETRMedium() | ||
| annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER) | ||
|
|
||
| def callback(frame, _): | ||
| detections = model.predict(frame) | ||
| detections = tracker.update(detections) | ||
| return annotator.annotate(frame, detections, labels=detections.tracker_id) | ||
|
|
||
| sv.process_video( | ||
| source_path="<INPUT_VIDEO_PATH>", | ||
| target_path="<OUTPUT_VIDEO_PATH>", | ||
| callback=callback, | ||
| ) | ||
| ``` | ||
|
|
||
| === "ultralytics" | ||
|
|
||
| ```python hl_lines="2 5 12" | ||
| import supervision as sv | ||
| from trackers import OCSORTTracker | ||
| from ultralytics import YOLO | ||
|
|
||
| tracker = OCSORTTracker() | ||
| model = YOLO("yolo11m.pt") | ||
| annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER) | ||
|
|
||
| def callback(frame, _): | ||
| result = model(frame)[0] | ||
| detections = sv.Detections.from_ultralytics(result) | ||
| detections = tracker.update(detections) | ||
| return annotator.annotate(frame, detections, labels=detections.tracker_id) | ||
|
|
||
| sv.process_video( | ||
| source_path="<INPUT_VIDEO_PATH>", | ||
| target_path="<OUTPUT_VIDEO_PATH>", | ||
| callback=callback, | ||
| ) | ||
| ``` | ||
|
|
||
| === "transformers" | ||
|
|
||
| ```python hl_lines="3 6 28" | ||
| import torch | ||
| import supervision as sv | ||
| from trackers import OCSORTTracker | ||
| from transformers import RTDetrV2ForObjectDetection, RTDetrImageProcessor | ||
|
|
||
| tracker = OCSORTTracker() | ||
| processor = RTDetrImageProcessor.from_pretrained("PekingU/rtdetr_v2_r18vd") | ||
| model = RTDetrV2ForObjectDetection.from_pretrained("PekingU/rtdetr_v2_r18vd") | ||
| annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER) | ||
|
|
||
| def callback(frame, _): | ||
| inputs = processor(images=frame, return_tensors="pt") | ||
| with torch.no_grad(): | ||
| outputs = model(**inputs) | ||
|
|
||
| h, w, _ = frame.shape | ||
| results = processor.post_process_object_detection( | ||
| outputs, | ||
| target_sizes=torch.tensor([(h, w)]), | ||
| threshold=0.5 | ||
| )[0] | ||
|
|
||
| detections = sv.Detections.from_transformers( | ||
| transformers_results=results, | ||
| id2label=model.config.id2label | ||
| ) | ||
|
|
||
| detections = tracker.update(detections) | ||
| return annotator.annotate(frame, detections, labels=detections.tracker_id) | ||
|
|
||
| sv.process_video( | ||
| source_path="<INPUT_VIDEO_PATH>", | ||
| target_path="<OUTPUT_VIDEO_PATH>", | ||
| callback=callback, | ||
| ) | ||
| ``` |
There was a problem hiding this comment.
Before v2.1.0 release I updated the format of similar examples for SORT and ByteTrack. Please make sure we follow similar pattern here.
| to the unmatched observations after the usual association. It attempts to recover tracks that were lost | ||
| due to object stopping or short-term occlusion. | ||
| Args: | ||
| lost_track_buffer (int): Number of frames to buffer when a track is lost. |
There was a problem hiding this comment.
Let's drop types from docstring, we only keep it in code. We are slowly doing the same in other repos. I did that in trackers before v2.1.0 release. I'm flagging it here, but we would need to do it in the whole PR.
trackers/utils/bbox_conversions.py
Outdated
| h = bbox[3] - bbox[1] | ||
| x = bbox[0] + w / 2.0 | ||
| y = bbox[1] + h / 2.0 | ||
| s = w * h # scale is just area |
There was a problem hiding this comment.
Comments like this seem redundent, it's a pretty simple math operation. You can point out in docstring. that scale is an area.
trackers/utils/bbox_conversions.py
Outdated
| @@ -0,0 +1,34 @@ | |||
| import numpy as np | |||
There was a problem hiding this comment.
would rename the whole file to converters.py
| from trackers.log import get_logger | ||
|
|
||
| __all__ = ["ByteTrackTracker", "SORTTracker"] | ||
| __all__ = ["OCSORTTracker", "SORTTracker"] |
There was a problem hiding this comment.
seem like this file is out of date, please make sure all develop chanegs are in this branch
| - ByteTrack: trackers/bytetrack.md | ||
| - SORT: trackers/core/sort/tracker.md | ||
| - DeepSORT: trackers/core/deepsort/tracker.md | ||
| - OC-SORT: trackers/core/ocsort/tracker.md |
There was a problem hiding this comment.
seem like this file is out of date, please make sure all develop chanegs are in this branch
| @@ -0,0 +1,180 @@ | |||
| from copy import deepcopy | |||
There was a problem hiding this comment.
why not move this whole file to core/ocsort and rename it to utils.py if it's OC-SORT specific? is this code entierly copy-pasted from their repo?
There was a problem hiding this comment.
ok! because before we were putting all tracker specific utils there i continued putting them there, but sounds good to do so
|
@AlexBodner can we close it? |
What does this PR do?
OC-SORT in process
Type of Change
Testing
Benchmark soccernet: https://colab.research.google.com/drive/1zzBf4xBSN9KBSDUTDQnMy7Zvny2DOeJL?usp=sharing