OC-SORT: a motion-only tracker built to survive occlusion and non-linear motion
[CVPR2023] The official repo for OC-SORT: Observation-Centric SORT on video Multi-Object Tracking. OC-SORT is simple, online and robust to occlusion/non-linear motion.
At a glance
- What is it?
- OC-SORT replaces SORT's Kalman-filter assumptions with observation-centric bookkeeping. The repository is a Python research codebase built on YOLOX, with a demo command, published benchmark tables and a stated 700 FPS association speed when detections are precomputed.
- Who is it for?
- Adopt OC-SORT if you already have detections and want a motion-only association stage you can read in an afternoon, or if you are reproducing the CVPR 2023 results on MOT17, MOT20, KITTI or DanceTrack. Do not adopt it if your sequences contain appearance-distinguishable targets that move unpredictably, because the tracker carries no visual descriptor by default and the README itself points to Deep OC-SORT for that case.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 147 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The failure mode in SORT that OC-SORT was written to fix
SORT and its Kalman-filter descendants estimate an object's state from a motion model and then correct that estimate with a detection. When an object is occluded, no detection arrives, so the filter coasts on its own prediction. The error accumulated during that coast is never repaired once the object reappears; the filter simply continues from a state that has drifted. The README frames OC-SORT as designed by recognizing and fixing limitations in the Kalman filter and SORT, and names crowded scenes and non-linear motion as the two conditions it targets. The intended user is someone doing video multi-object tracking who has detections already and wants the association stage to hold identity through gaps. It is a research artifact from a CVPR 2023 paper, not a packaged tracking service. The repository description says online, meaning it processes frames as they arrive rather than requiring the whole sequence up front, and the benchmark table in the README reports results on MOT17, MOT20, KITTI cars and pedestrians, DanceTrack-test and CroHD HeadTrack.
Observation-centric re-update and the three places observations re-enter the filter
The mechanism the README highlights is Observation-centric Re-Update, abbreviated ORU. The idea is that when a track is lost and later re-associated with a detection, the filter should not resume from the drifted predicted state. Instead the observations gathered along the way are used to re-estimate the trajectory, so the correction is applied retroactively rather than only at the current frame. The README notes a naming change: the preprint originally called this OOS, and it was renamed ORU in the March 2023 revision, so anyone reading an older copy of the paper will see the other term. Beyond ORU, the repository advertises flexibility to integrate different detectors and matching modules, including appearance similarity, and a changelog entry from April 2022 mentions support for integration with BYTE and multiple cost metrics such as GIoU and CIoU. Those association cost choices matter because the tracker is motion-only by default: the cost between a predicted box and a detection is geometric, and swapping IoU for GIoU or CIoU changes how that geometric disagreement is scored. The pipeline diagram and the ORU diagram in assets/ are the two figures the README offers for the architecture, and the prose does not go further than that, so the precise update equations have to come from the arXiv paper rather than the repository text.
Running the demo: one command and the flags it needs
The README gives a single concrete invocation. It runs the tracker on a demo video and writes an annotated output file:
python3 tools/demo_track.py --demo_type video -f exps/example/mot/yolox_dancetrack_test.py -c pretrained/ocsort_dance_model.pth.tar --path videos/dance_demo.mp4 --fp16 --fuse --save_result --out_path demo_out.mp4
Reading the flags: --demo_type selects the input modality, -f points at a YOLOX experiment config under exps/example/mot/, -c is the checkpoint path under pretrained/, --path is the source video, --fp16 and --fuse are inference optimizations, and --save_result with --out_path controls writing the result. Two of those paths are not in the repository as shipped. The checkpoint pretrained/ocsort_dance_model.pth.tar has to be obtained separately, and the README directs readers to docs/MODEL_ZOO.md for available YOLOX weights. The input video videos/dance_demo.mp4 is described as coming from YouTube. Installation instructions live in docs/INSTALL.md, and getting started guidance in docs/GET_STARTED.md. Because the codebase is built on YOLOX, the install path follows YOLOX's, which means a working PyTorch and CUDA setup before anything runs. The repository also documents deployment routes: docs/DEPLOY.md covers ONNX, TensorRT and ncnn, and a C++ implementation is documented under deploy/OCSort/cpp/Readme.md, contributed in July 2023.
What the benchmark table does and does not tell you
The README publishes HOTA, AssA, IDF1, MOTA, false positives, false negatives, ID switches and fragmentations across seven evaluation settings. MOT17 private reports HOTA 63.2 and IDF1 77.5; MOT20 private reports HOTA 62.4 and IDF1 76.4; DanceTrack-test reports HOTA 55.1 but AssA of only 38.0, which is the number worth staring at. DanceTrack is the dataset of similar-looking targets in non-linear motion, and a low association accuracy there is consistent with a tracker that has no appearance model to separate two people who look alike and move unpredictably. The README is candid about provenance: results come from reusing detections of previous methods and shared hyper-parameters, and tuning per dataset may yield higher numbers. That caveat cuts both ways. It means the table is not a clean measure of the tracker in isolation, and it means your own numbers will depend heavily on the detector feeding it. Two speed figures are given: about 28 FPS end to end on an RTX 2080Ti, and 700 FPS for the OC-SORT association step alone on an i9 at 3.0GHz. The gap between those two numbers is the detector. If you supply boxes from elsewhere, the association cost is small; if you run the bundled YOLOX detector, the detector dominates the frame budget.
Where OC-SORT is the wrong tool
The clearest boundary is appearance. OC-SORT is described as a pure motion-model-based tracker. Two pedestrians who cross paths, wear similar clothing and move erratically present a problem the motion model alone cannot resolve, and the DanceTrack AssA figure is the evidence in the repository's own table. The README's own answer to this is Deep OC-SORT, which it says adds an adaptive appearance similarity-based association on top of OC-SORT and was accepted to ICIP 2023. If your scenario is dominated by appearance ambiguity, you are looking at the wrong repository. A second boundary is deployment maturity. The repository has no releases retrieved, the mmtracking integration is described in the changelog as still in-preview with performance on more datasets to be verified, and the main entry point is a research demo script rather than a library with a stable API. The March 2026 changelog entry says the Python implementation was refactored for a 1.5x to 2x inference speedup. A refactor of that kind can move or rename internal classes, so code that imported tracker internals from an earlier commit may need adjustment. That is a real cost for anyone who pinned to the old layout. A third boundary is the detector coupling: the demo path assumes YOLOX-format experiment configs and checkpoints, and swapping in a different detector means either going through the mmtracking route or writing your own adapter.
Alternatives and the actual difference in approach
ByteTrack is the most direct comparison, and the relationship is documented rather than implied: the README states the codebase is built upon ByteTrack, alongside YOLOX and filterpy, and ByteTrack is MIT licensed. ByteTrack's association strategy is built around using low-score detection boxes in a second matching round, recovering objects that a confidence threshold would have discarded. OC-SORT's answer to lost tracks is different: it keeps the Kalman filter but changes how the filter is corrected after a gap, re-estimating from the observations collected during the gap. One reuses weak detections at association time; the other revisits the state estimate after association succeeds. Deep OC-SORT is the other comparison worth naming, and it is the same authors' lineage rather than a competitor: it keeps the OC-SORT motion machinery and adds appearance similarity to the association cost. The trade is inference cost and a second model to load against better identity retention when targets look alike. Between plain OC-SORT and Deep OC-SORT the deciding question is whether your failure cases are geometric or visual, and the README's own DanceTrack numbers suggest visual. For a fully different design, a transformer-based tracker that treats tracking as a query problem would be the category to look at, but nothing in this repository's material compares against one.
Licence, dependencies and what an upgrade actually costs
OC-SORT is MIT licensed, and the README states that filterpy and ByteTrack are also MIT. YOLOX, which the codebase is built upon, uses Apache License 2.0. That mixture is worth noting if you redistribute a combined binary, because the two licences carry different notice and patent terms; this is a description of what the repository states, not legal advice, and a lawyer should read the actual licence texts before you ship. The dependency surface is the ongoing cost. Because the codebase is built on YOLOX, upgrades to PyTorch or CUDA can break the build through YOLOX rather than through OC-SORT itself, and the deployment docs under docs/DEPLOY.md covering ONNX, TensorRT and ncnn are the places where that coupling shows up. The C++ path under deploy/OCSort/cpp/ is a separate implementation with its own build, so choosing it means maintaining two code paths if you also use the Python tracker. There are no tagged releases in the retrieved metadata, which means versioning is by commit and there is no changelog file to diff between versions; the README's News section is the closest thing to one. Practically, pin to a specific commit hash rather than tracking master, and re-read the News entries before moving that pin, because the 2026 refactor is exactly the kind of change that alters internal interfaces without a release note.
Editorial conclusion
Adopt OC-SORT if you already have detections and want a motion-only association stage you can read in an afternoon, or if you are reproducing the CVPR 2023 results on MOT17, MOT20, KITTI or DanceTrack. Do not adopt it if your sequences contain appearance-distinguishable targets that move unpredictably, because the tracker carries no visual descriptor by default and the README itself points to Deep OC-SORT for that case. Before committing, check the docs/INSTALL.md dependency list against your CUDA and PyTorch versions, and confirm whether the 2026 refactor changed the tracker API your code calls.
Community notes