{"notes":[{"id":"object-detection/rt-detr","category":"object-detection","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"RT-DETR","subtitle":"Putting NMS on the Clock","author":"Z. Yuan","paperDate":"2023-04-17","publishedOn":"2025-01-29","world":"external/rt-detr","paperTitle":"DETRs Beat YOLOs on Real-time Object Detection","paperUrl":"https://arxiv.org/abs/2304.08069","bibliography":{"title":"DETRs Beat YOLOs on Real-time Object Detection","authors":["Yian Zhao","Wenyu Lv","Shangliang Xu","Jinman Wei","Guanzhong Wang","Qingqing Dang","Yi Liu","Jie Chen"],"url":"https://arxiv.org/abs/2304.08069","pdfUrl":"https://arxiv.org/pdf/2304.08069v3","codeUrl":"https://github.com/lyuwenyu/RT-DETR","preprint":{"id":"2304.08069","submittedOn":"2023-04-17","url":"https://arxiv.org/abs/2304.08069"},"publication":{"venue":"CVPR","year":2024,"kind":"conference","url":"https://openaccess.thecvf.com/content/CVPR2024/html/Zhao_DETRs_Beat_YOLOs_on_Real-time_Object_Detection_CVPR_2024_paper.html"},"citation":"@misc{objectdetectionrtdetr2023,\n  title = {{DETRs Beat YOLOs on Real-time Object Detection}},\n  author = {Yian Zhao and Wenyu Lv and Shangliang Xu and Jinman Wei and Guanzhong Wang and Qingqing Dang and Yi Liu and Jie Chen},\n  year = {2023},\n  eprint = {2304.08069},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/2304.08069}\n}\n","citationPath":"/content/papers/citations/object-detection/rt-detr.cbe42f7a5b6c.bib"},"thumbnail":{"src":"/content/papers/assets/7e2de3c38daff439f51d86ec04a7bd391c3f708b817ae539f3c4df7c5546f4d6.png","width":1360,"height":332},"locale":"en","path":"/content/papers/en/object-detection/rt-detr.f2b9f4caa500.md","headings":[{"id":"problem-definition","text":"Problem Definition","depth":2},{"id":"how-much-time-does-nms-take","text":"How Much Time Does NMS Take?","depth":3},{"id":"an-end-to-end-stopwatch","text":"An End-to-End Stopwatch","depth":3},{"id":"where-is-detr-slow","text":"Where Is DETR Slow?","depth":3},{"id":"solution","text":"Solution","depth":2},{"id":"the-big-picture","text":"The Big Picture","depth":3},{"id":"the-encoders-arithmetic","text":"The Encoder's Arithmetic","depth":3},{"id":"aifi-self-attention-only-in-s5","text":"AIFI: Self-Attention Only in S5","depth":3},{"id":"ccff-cross-scale-fusion-by-convolution","text":"CCFF: Cross-Scale Fusion by Convolution","depth":3},{"id":"picking-300-queries","text":"Picking 300 Queries","depth":3},{"id":"the-decoder-dropping-the-last-few-layers","text":"The Decoder: Dropping the Last Few Layers","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"against-yolo-and-dino","text":"Against YOLO and DINO","depth":3},{"id":"how-should-the-thresholds-be-set","text":"How Should the Thresholds Be Set?","depth":3},{"id":"on-another-machine","text":"On Another Machine","depth":3},{"id":"duplicate-boxes-still-turn-up","text":"Duplicate Boxes Still Turn Up","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"object-detection/detr","relation":"referenced","topic":""},{"id":"object-detection/deformable-detr","relation":"referenced","topic":""},{"id":"feature-fusion/panet","relation":"referenced","topic":""}]},{"id":"object-detection/detr","category":"object-detection","legacyPath":"object-detection/2005-detr","legacySlug":"2005-detr","legacyPaths":[],"title":"DETR","subtitle":"A Cross-Domain Pioneer","author":"Z. Yuan","paperDate":"2020-05-26","publishedOn":"2024-06-04","paperTitle":"End-to-End Object Detection with Transformers","paperUrl":"https://www.ecva.net/papers/eccv_2020/papers_ECCV/html/832_ECCV_2020_paper.php","bibliography":{"title":"End-to-End Object Detection with Transformers","authors":["Nicolas Carion","Francisco Massa","Gabriel Synnaeve","Nicolas Usunier","Alexander Kirillov","Sergey Zagoruyko"],"url":"https://www.ecva.net/papers/eccv_2020/papers_ECCV/html/832_ECCV_2020_paper.php","pdfUrl":"https://www.ecva.net/papers/eccv_2020/papers_ECCV/papers/123460205.pdf","codeUrl":"https://github.com/facebookresearch/detr","preprint":{"id":"2005.12872","submittedOn":"2020-05-26","url":"https://arxiv.org/abs/2005.12872"},"publication":{"venue":"ECCV","year":2020,"kind":"conference","url":"https://www.ecva.net/papers/eccv_2020/papers_ECCV/html/832_ECCV_2020_paper.php"},"citation":"@misc{objectdetectiondetr2020,\n  title = {{End-to-End Object Detection with Transformers}},\n  author = {Nicolas Carion and Francisco Massa and Gabriel Synnaeve and Nicolas Usunier and Alexander Kirillov and Sergey Zagoruyko},\n  year = {2020},\n  eprint = {2005.12872},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/2005.12872}\n}\n","citationPath":"/content/papers/citations/object-detection/detr.5258ffe0b9a0.bib"},"thumbnail":{"src":"/content/papers/assets/dd7e8441e6460ff562cf558374789924518fafaed7ecde0e3e35ee778c316330.jpg","width":1024,"height":266},"locale":"en","path":"/content/papers/en/object-detection/detr.493e749cd884.md","headings":[{"id":"problem-definition","text":"Problem Definition","depth":2},{"id":"solution","text":"Solution","depth":2},{"id":"model-architecture","text":"Model Architecture","depth":3},{"id":"loss-design","text":"Loss Design","depth":3},{"id":"dataset","text":"Dataset","depth":3},{"id":"technical-details","text":"Technical Details","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"how-does-it-perform-this-time","text":"How does it perform this time?","depth":3},{"id":"component-analysis-of-the-model","text":"Component Analysis of the Model","depth":3},{"id":"model-behavior-analysis","text":"Model Behavior Analysis","depth":3},{"id":"generalization-to-unseen-object-counts","text":"Generalization to Unseen Object Counts","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{"defining-the-problem":"problem-definition","solving-the-problem":"solution","from-an-image-to-a-set-of-objects":"model-architecture","match-first-then-compute-the-loss":"loss-design","experimental-results-and-discussion":"discussion","how-did-it-do-start-with-the-conditions":"how-does-it-perform-this-time","which-components-matter":"component-analysis-of-the-model","what-did-the-queries-learn":"model-behavior-analysis"},"guide":null,"relatedReading":[{"id":"object-detection/deformable-detr","relation":"next","topic":"Set prediction and attention-based detection"},{"id":"object-detection/smca-detr","relation":"comparison","topic":"Faster convergence for Transformer detectors"}]},{"id":"object-detection/deformable-detr","category":"object-detection","legacyPath":"object-detection/2010-deformable-detr","legacySlug":"2010-deformable-detr","legacyPaths":[],"title":"Deformable DETR","subtitle":"Deformable Attention Mechanism","author":"Z. Yuan","paperDate":"2020-10-08","publishedOn":"2024-09-20","paperTitle":"Deformable DETR: Deformable Transformers for End-to-End Object Detection","paperUrl":"https://arxiv.org/abs/2010.04159","bibliography":{"title":"Deformable DETR: Deformable Transformers for End-to-End Object Detection","authors":["Xizhou Zhu","Weijie Su","Lewei Lu","Bin Li","Xiaogang Wang","Jifeng Dai"],"url":"https://arxiv.org/abs/2010.04159","pdfUrl":"https://arxiv.org/pdf/2010.04159","codeUrl":null,"preprint":{"id":"2010.04159","submittedOn":"2020-10-08","url":"https://arxiv.org/abs/2010.04159"},"publication":{"venue":"ICLR","year":2021,"kind":"conference","url":"https://arxiv.org/abs/2010.04159"},"citation":"@misc{objectdetectiondeformabledetr2020,\n  title = {{Deformable DETR: Deformable Transformers for End-to-End Object Detection}},\n  author = {Xizhou Zhu and Weijie Su and Lewei Lu and Bin Li and Xiaogang Wang and Jifeng Dai},\n  year = {2020},\n  eprint = {2010.04159},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/2010.04159}\n}\n","citationPath":"/content/papers/citations/object-detection/deformable-detr.df721a30472e.bib"},"thumbnail":{"src":"/content/papers/assets/36edfc5595a85c73fcdc9a4bbb9e1ca512e1f100676eb7c37203d71c84905c05.jpg","width":1224,"height":752},"locale":"en","path":"/content/papers/en/object-detection/deformable-detr.68972544ff9b.md","headings":[{"id":"problem-definition","text":"Problem Definition","depth":2},{"id":"problem-solution","text":"Problem Solution","depth":2},{"id":"deformable-attention","text":"Deformable Attention","depth":3},{"id":"multi-scale-computation","text":"Multi-Scale Computation","depth":3},{"id":"model-architecture","text":"Model Architecture","depth":3},{"id":"code-breakdown","text":"Code Breakdown","depth":3},{"id":"training-strategy","text":"Training Strategy","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"comparison-with-detr","text":"Comparison with DETR","depth":3},{"id":"ablation-studies","text":"Ablation Studies","depth":3},{"id":"sota-comparison","text":"SOTA Comparison","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"object-detection/detr","relation":"background","topic":"Set prediction and attention-based detection"},{"id":"object-detection/h-detr","relation":"next","topic":"Set prediction and attention-based detection"},{"id":"object-detection/smca-detr","relation":"comparison","topic":"Faster convergence for Transformer detectors"}]},{"id":"feature-fusion/panet","category":"feature-fusion","legacyPath":"feature-fusion/1803-panet","legacySlug":"1803-panet","legacyPaths":[],"title":"PANet","subtitle":"Give Me a Shortcut","author":"Z. Yuan","paperDate":"2018-03-05","publishedOn":"2024-04-06","paperTitle":"Path Aggregation Network for Instance Segmentation","paperUrl":"https://arxiv.org/abs/1803.01534","bibliography":{"title":"Path Aggregation Network for Instance Segmentation","authors":["Shu Liu","Lu Qi","Haifang Qin","Jianping Shi","Jiaya Jia"],"url":"https://arxiv.org/abs/1803.01534","pdfUrl":"https://arxiv.org/pdf/1803.01534","codeUrl":null,"preprint":{"id":"1803.01534","submittedOn":"2018-03-05","url":"https://arxiv.org/abs/1803.01534"},"publication":{"venue":"CVPR","year":2018,"kind":"conference","url":"https://arxiv.org/abs/1803.01534"},"citation":"@misc{featurefusionpanet2018,\n  title = {{Path Aggregation Network for Instance Segmentation}},\n  author = {Shu Liu and Lu Qi and Haifang Qin and Jianping Shi and Jiaya Jia},\n  year = {2018},\n  eprint = {1803.01534},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1803.01534}\n}\n","citationPath":"/content/papers/citations/feature-fusion/panet.31d49af45ee9.bib"},"thumbnail":{"src":"/content/papers/assets/549012fa5498c4bbe44cfad4f4c54ed4eac5e7f0cdc71ae6308bb1ee6a4942ed.jpg","width":1024,"height":348},"locale":"en","path":"/content/papers/en/feature-fusion/panet.bccaab9f2654.md","headings":[{"id":"defining-the-problem","text":"Defining the Problem","depth":2},{"id":"solving-the-problem","text":"Solving the Problem","depth":2},{"id":"panet-model-design","text":"PANet Model Design","depth":3},{"id":"path-aggregation-fpn","text":"Path Aggregation FPN","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"how-does-it-compare-to-basic-fpn","text":"How Does It Compare to Basic FPN?","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"feature-fusion/fpn","relation":"background","topic":"Fusing multiscale features for detection"},{"id":"feature-fusion/bifpn","relation":"next","topic":"Fusing multiscale features for detection"}]}],"text":"In April 2023, authors from Baidu and Peking University posted a paper on arXiv whose title, DETRs Beat YOLOs, claims that DETR beats YOLO at real-time object detection.\n\nTheir model is called RT-DETR (Real-Time DEtection TRansformer). It reads a 640×640 photo and outputs 300 predictions, each made of a box, a class and a score; to use them, you just drop the low-scoring boxes with a score threshold, and no NMS follows. It is going after YOLO's jobs, such as the object tracking, video surveillance and self-driving cars the paper lists at the start, which have to process dozens of images per second. The paper was later published at CVPR 2024.\n\nAt the time, that title was a bold claim. The most accurate DETR in the paper's Table 2 is DINO, whose ResNet-50 version reaches 50.9 AP on COCO but manages only 5 images per second on a T4 GPU (with 800×1333 input). YOLO's large models also reach 52 or 53 AP on COCO, at dozens of images per second and up.\n\nTo say that DETR wins, you first have to settle how YOLO's speed is measured. YOLO's output is only usable after NMS, and whether NMS time is counted, and at which thresholds, changes the measured speed a lot. The paper's first step is to put NMS back on the stopwatch; then it goes back and breaks down where DETR's time goes.\n\n## Problem Definition\n\n### How Much Time Does NMS Take?\n\nYOLO guesses boxes at every position of its feature maps. For a 640×640 input, YOLOv8 has 80×80 + 40×40 + 20×20 = 8,400 positions across three feature maps at strides 8, 16 and 32, with one box per position; YOLOv5 places 3 anchors at each position, which makes 25,200. Several positions near the same object all report boxes, so NMS (non-maximum suppression) is needed to clear out the duplicates.\n\nNMS has two thresholds. A confidence threshold first removes boxes whose scores are too low; then, within each class, NMS keeps the highest-scoring box, deletes the boxes whose IoU with it exceeds a threshold, and repeats this on the boxes that remain. IoU is the area of the intersection of two boxes divided by the area of their union.\n\nSo how much work NMS does depends on how many boxes pass the confidence threshold. On the same input, the authors counted how many boxes YOLOv5 and YOLOv8 have left at different confidence thresholds. The horizontal axis is the confidence threshold and the vertical axis the number of boxes; blue is the anchor-based YOLOv5 and orange the anchor-free YOLOv8:\n\n[![Bar chart. The horizontal axis shows the confidence thresholds 0.001, 0.005, 0.01, 0.05, 0.1 and 0.25; the vertical axis is the number of remaining boxes, from 0 to 10,000. The blue bars are YOLOv5, at a little over 9,000 at 0.001, falling step by step to about 600 as the threshold rises; the orange bars are YOLOv8, at a little over 3,000 at 0.001, falling to about 400. At every threshold, blue is higher than orange.](/content/papers/assets/3ce51df5cdcf3f7995e63085f9c6925d29364b00decdae24bb9a6f2b628bacb1.png)](/content/papers/assets/3ce51df5cdcf3f7995e63085f9c6925d29364b00decdae24bb9a6f2b628bacb1.png)\n\n*Figure 2 from the paper, Zhao et al., excerpted from [**page 3 of the v3 PDF**](https://arxiv.org/pdf/2304.08069v3#page=3). The number of boxes left for the same input at different confidence thresholds.*\n\nAt a confidence threshold of 0.001, YOLOv5 keeps over 9,000 boxes and YOLOv8 over 3,000; raise the threshold to 0.25 and both are down to a few hundred. At every threshold, YOLOv5 has more boxes than YOLOv8.\n\nNext, the authors measured YOLOv8's AP and the NMS execution time on COCO val2017. NMS uses TensorRT's efficientNMSPlugin and runs on a T4 GPU with TensorRT FP16:\n\n| Confidence threshold | IoU threshold | AP | NMS time (ms) |\n| ---: | ---: | ---: | ---: |\n| 0.001 | 0.5 | 52.1 | 2.24 |\n| 0.001 | 0.6 | 52.6 | 2.29 |\n| 0.001 | 0.7 | 52.9 | 2.36 |\n| 0.001 | 0.8 | 52.8 | 2.46 |\n| 0.01 | 0.7 | 52.4 | 1.73 |\n| 0.05 | 0.7 | 51.2 | 1.06 |\n\n*Table: Compiled from Table 1 of the paper. The original table has two halves, one with a fixed confidence threshold and one with a fixed IoU threshold; here they are merged into one. The table doesn't state the YOLOv8 size; its 52.9 AP matches YOLOv8-L in Table 2.*\n\nStart with the first four rows. With the confidence threshold fixed at 0.001, raising the IoU threshold from 0.5 to 0.8 increases the NMS time from 2.24 to 2.46 ms. The higher the IoU threshold, the fewer boxes each round deletes, and the more rounds have to run. AP is highest at 0.7.\n\nNow the three rows with the IoU threshold fixed at 0.7. Raising the confidence threshold from 0.001 to 0.05 cuts the NMS time from 2.36 to 1.06 ms, by more than half, while AP drops from 52.9 to 51.2.\n\nThe best result, 52.9 AP, comes at confidence 0.001 and IoU 0.7, and this setting has the second-longest NMS time in the table. If YOLO wants that AP, it has to pay that time; to save time, it has to give up some AP.\n\nThe times in the table cover only part of the work. efficientNMSPlugin contains several kernels, including EfficientNMSFilter, RadixSort and EfficientNMS, and Table 1 lists only EfficientNMS.\n\nThe appendix also shows YOLOv8-L's predictions under several threshold settings. With too low a confidence threshold, a pile of extra boxes appears in the image; with a low IoU threshold, objects that occlude each other get deleted as duplicates, and with a high one, overlapping duplicates stay. The authors find the confidence threshold reasonably easy to tune and the IoU threshold hard to set accurately.\n\nYet when YOLO reports speed, it usually measures only the model itself, without NMS (§3.1). NMS is missing from the speed table, while the AP is computed with NMS attached and a very low confidence threshold.\n\n### An End-to-End Stopwatch\n\nSo the authors set up an end-to-end benchmark (§3.2):\n\n- The data is COCO val2017, measured image by image and averaged, because NMS time varies with the input.\n- YOLO gets TensorRT's NMS plugin attached, with the thresholds each model used to obtain its reported AP. The official speed-test script's default for YOLOv8 is confidence 0.001, IoU 0.7 and at most 300 output boxes.\n- I/O and memory copies are excluded; measurements run on a T4 GPU with TensorRT FP16.\n\nTimed with this stopwatch, the authors found that at comparable accuracy, anchor-free YOLOs are faster than anchor-based ones, because the latter output more boxes and NMS takes longer. Among the models they tested, the anchor-based ones had three times as many boxes, consistent with the 25,200 versus 8,400 computed above.\n\n### Where Is DETR Slow?\n\nDETR has no NMS, so that time is saved from the start. Its trouble lies in the model itself.\n\n\n> [!TIP]\n> \n> If you haven't read DETR, here is some background. DETR does object detection with a Transformer, preparing a fixed number of queries, each of which outputs one box and one class. During training, the Hungarian algorithm matches predictions to annotations one to one, so each object has exactly one query responsible for it, and inference needs no NMS. The later Deformable DETR feeds multi-scale features into the encoder and has attention look at only a few sampling points, which makes convergence much faster. For both papers, see our notes:\n> \n> - **[[20.05] DETR: A Cross-Domain Pioneer](/blog/papers/object-detection/detr)**\n> - **[[20.10] Deformable DETR: Deformable Attention Mechanism](/blog/papers/object-detection/deformable-detr)**\n\n\nMulti-scale features help DETR converge faster and reach higher accuracy, at the cost of a suddenly much longer sequence for the encoder to process. Deformable attention had already cut the computation, yet the encoder still became the computational bottleneck. The authors cite an analysis from D²ETR, which found that in Deformable DETR the encoder accounts for 49% of the GFLOPs but contributes only 11% of the AP.\n\nSo how should the encoder be cut? If you remove it entirely, how much accuracy is lost? If you keep only part of it, which part should stay?\n\n## Solution\n\n### The Big Picture\n\nRT-DETR is made up of three parts, a backbone, a hybrid encoder and a decoder. The backbone provides the features of its last three stages, $S_3$, $S_4$ and $S_5$; the hybrid encoder turns them into a sequence of image features; query selection picks a fixed number of features from that sequence as the starting points of the queries; and the decoder refines these queries layer by layer and outputs classes and boxes.\n\nTaking a 640×640 image, we drew the size at each stage:\n\n[![Data-flow diagram of RT-DETR. A 640×640 image passes through a ResNet backbone, which yields three feature levels, S3, S4 and S5, of size 80×80, 40×40 and 20×20, corresponding to 6,400, 1,600 and 400 positions. A 1×1 convolution first converts all three levels to 256 channels. Only S5 enters AIFI, where it is flattened into 400 tokens for one layer of self-attention, producing F5; S3 and S4 skip self-attention and pass straight down. All three enter CCFF, which uses convolutions to fuse adjacent scales top-down and then bottom-up, producing three levels of 80×80, 40×40 and 20×20 that are flattened and concatenated into 8,400 features of 256 dimensions. Query selection takes the top 300 by score, using the features as content and the predicted boxes as starting points. The decoder has 6 layers, each followed by its own set of prediction heads; a red line in the figure shows inference stopping at layer 4, with the last two layers left out. The final output is 300 boxes, classes and scores, filtered with a score threshold and no NMS.](/content/papers/assets/8e2d050c9352772d789f19ade58cec81b5345d6cd86289b7a51014c231742ca8.png)](/content/papers/assets/8e2d050c9352772d789f19ade58cec81b5345d6cd86289b7a51014c231742ca8.png)\n\n*Figure: Drawn for this note, with a ResNet-50 backbone and 640×640 input as the example; stopping the decoder at layer 4 is just one example.*\n\nNext, we follow this figure from the encoder all the way to the decoder.\n\n### The Encoder's Arithmetic\n\nFirst, let's count the positions in each of the three feature levels. After flattening, each position is one token:\n\n```python\nH = W = 640\nstrides = {\"S3\": 8, \"S4\": 16, \"S5\": 32}\ntokens = {k: (H // s) * (W // s) for k, s in strides.items()}\ntotal = sum(tokens.values())\n\nfor k, n in tokens.items():\n    side = H // strides[k]\n    print(f\"{k}: {side}×{side} = {n} tokens, {n / total:.0%} of the total, {n * n / 1e6:.2f}M token pairs\")\nprint(\"All three levels:\", total, \"tokens\")\n\npairs_each = sum(n * n for n in tokens.values())\npairs_s5 = tokens[\"S5\"] ** 2\nprint(f\"Self-attention in each level: {pairs_each / 1e6:.2f}M pairs; S5 only: {pairs_s5 / 1e6:.2f}M pairs, a {pairs_each / pairs_s5:.0f}x difference\")\n```\n\n```text\nS3: 80×80 = 6400 tokens, 76% of the total, 40.96M token pairs\nS4: 40×40 = 1600 tokens, 19% of the total, 2.56M token pairs\nS5: 20×20 = 400 tokens, 5% of the total, 0.16M token pairs\nAll three levels: 8400 tokens\nSelf-attention in each level: 43.68M pairs; S5 only: 0.16M pairs, a 273x difference\n```\n\nS3 alone holds 76% of the tokens. Ordinary self-attention pairs every token with all the tokens in the same level, which gives over 40 million pairs in S3 alone; doing it only in S5 takes just 160,000 pairs.\n\nThe authors check this arithmetic with a set of encoder variants. From left to right, the figure shows five encoders, A to E, and the three arrows under each box stand for the three feature levels. SSE is a single-scale Transformer encoder, MSE a multi-scale Transformer encoder, and CSF cross-scale fusion:\n\n[![Five boxes side by side, one for each encoder variant. A has only Concat; B is SSE followed by Concat; C is Concat followed by MSE; D is SSE followed by CSF; E is AIFI followed by CCFF. The arrows below mark A to B as adding intra-scale interaction, B to C as adding cross-scale interaction, C to D as separating the two, and D to E as an enhanced version.](/content/papers/assets/7e2de3c38daff439f51d86ec04a7bd391c3f708b817ae539f3c4df7c5546f4d6.png)](/content/papers/assets/7e2de3c38daff439f51d86ec04a7bd391c3f708b817ae539f3c4df7c5546f4d6.png)\n\n*Figure 3 from the paper, Zhao et al., excerpted from [**page 4 of the v3 PDF**](https://arxiv.org/pdf/2304.08069v3#page=4). The structure of the five encoder variants.*\n\nEvery variant starts from DINO-Deformable-R50, swaps in RT-DETR's lighter data loading and decoder, and trains for 12 epochs. The table has one extra row, $\\mathrm{D}_{S_5}$, which has the same structure as D except that SSE processes only S5:\n\n| Variant | What the encoder does | AP | Params (M) | Latency (ms) |\n| --- | --- | ---: | ---: | ---: |\n| A | No encoder; the three levels are concatenated directly | 43.0 | 31 | 7.2 |\n| B | The three levels share one single-scale Transformer layer, each doing intra-scale interaction, then get concatenated | 44.9 | 32 | 11.1 |\n| C | B's results are concatenated and fed into a multi-scale Transformer encoder | 45.6 | 32 | 13.3 |\n| D | Intra-scale interaction goes to a single-scale Transformer, cross-scale fusion to a PANet-style structure | 46.4 | 35 | 12.2 |\n| $\\mathrm{D}_{S_5}$ | Same as D, but only S5 does intra-scale interaction | 46.8 | 35 | 7.9 |\n| E | AIFI + CCFF, which is RT-DETR's design | 47.9 | 42 | 9.3 |\n\n*Table: Table 3 of the paper; the \"What the encoder does\" column is compiled from §4.2.*\n\nGoing down row by row:\n\n1. **A → B**: AP rises by 1.9 and latency by 54%. Intra-scale interaction helps, but self-attention in every level is expensive.\n2. **B → C**: AP rises by another 0.7 and latency by another 20%. Cross-scale interaction helps too, but the multi-scale encoder costs even more.\n3. **C → D**: Separating intra-scale interaction from cross-scale fusion adds 0.8 AP and actually cuts latency by 8%.\n4. **D → $\\mathrm{D}_{S_5}$**: Keeping self-attention only in S5 cuts latency from 12.2 to 7.9 ms, a 35% reduction, and AP still rises by 0.4.\n5. **D → E**: Switching to AIFI and CCFF adds 1.5 AP and 20% more parameters, with 24% less latency.\n\nStep 4 removes the self-attention in S3 and S4, the more than 40 million pairs we just computed, and latency falls by 4.3 ms. Compared with A, which has no encoder at all, the final E adds only 2.1 ms of latency and scores 4.9 AP higher.\n\nWhy keep only S5? The authors argue that high-level features carry the semantics of objects, so self-attention at this level can capture the relationships between different objects and concepts in the image and help later modules locate and recognize them; low-level features lack semantics, so intra-scale interaction there is redundant and may even duplicate or confuse the high-level interaction. The $\\mathrm{D}_{S_5}$ row supports this view, computing that much less and still scoring 0.4 AP higher.\n\n### AIFI: Self-Attention Only in S5\n\nThe paper writes the hybrid encoder in three lines:\n\n$$\n\\begin{aligned}\n\\mathcal{Q} = \\mathcal{K} = \\mathcal{V} &= \\mathrm{Flatten}(S_5) \\\\\nF_5 &= \\mathrm{Reshape}(\\mathrm{AIFI}(\\mathcal{Q}, \\mathcal{K}, \\mathcal{V})) \\\\\n\\mathcal{O} &= \\mathrm{CCFF}(\\{S_3, S_4, F_5\\})\n\\end{aligned}\n$$\n\nAIFI is just one standard Transformer encoder layer. S5 is flattened into a sequence, Q, K and V all come from it, and after self-attention and the feed-forward network the result is folded back into a 20×20 shape. Let's keep the same image moving through, with random numbers standing in for the backbone outputs for now:\n\n```python\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\ntorch.manual_seed(0)\n# Outputs of the last three ResNet-50 stages, replaced here by random numbers\nS3 = torch.randn(1, 512, 80, 80)\nS4 = torch.randn(1, 1024, 40, 40)\nS5 = torch.randn(1, 2048, 20, 20)\n\n# First, a 1×1 convolution converts all three levels to 256 channels\nproj = nn.ModuleList(nn.Conv2d(c, 256, 1) for c in (512, 1024, 2048))\nS3, S4, S5 = (p(x) for p, x in zip(proj, (S3, S4, S5)))\n\n# AIFI: flatten only S5 into a sequence and pass it through one Transformer encoder layer\naifi = nn.TransformerEncoderLayer(d_model=256, nhead=8, dim_feedforward=1024, batch_first=True)\nseq = S5.flatten(2).transpose(1, 2)\nF5 = aifi(seq).transpose(1, 2).reshape(1, 256, 20, 20)\nprint(\"AIFI input\", tuple(seq.shape), \"→ F5\", tuple(F5.shape))\n```\n\n```text\nAIFI input (1, 400, 256) → F5 (1, 256, 20, 20)\n```\n\nThe sizes here follow Table A in the appendix, with an embedding dimension of 256, 8 heads, a feed-forward width of 1024 and a single layer. The official code also adds a 2D sin-cos positional encoding to Q and K, which the demo leaves out.\n\n### CCFF: Cross-Scale Fusion by Convolution\n\nCCFF follows PANet's route, first top-down and then bottom-up, and at each step fuses the features of two adjacent levels into a new level. The fusion block (Figure 5) concatenates the features of the two adjacent levels and splits them into two paths, each going through a 1×1 convolution; one path then goes through N RepBlocks, and finally the two paths are added element-wise. RT-DETR uses N = 3.\n\nA RepBlock is made of RepConvs, the RepVGG-style design that has multiple branches during training and merges them into a single 3×3 convolution for inference. The demo below uses plain 3×3 convolutions instead, and also leaves out BN, SiLU, and the extra 1×1 convolution the official code applies before upsampling:\n\n```python\nclass Fusion(nn.Module):\n    \"\"\"Figure 5's fusion block: two 1×1 conv paths, one followed by N conv blocks, then added element-wise\"\"\"\n    def __init__(self, n=3):\n        super().__init__()\n        self.a = nn.Conv2d(512, 256, 1)\n        self.b = nn.Conv2d(512, 256, 1)\n        self.blocks = nn.Sequential(*[nn.Conv2d(256, 256, 3, padding=1) for _ in range(n)])\n\n    def forward(self, x, y):\n        z = torch.cat([x, y], dim=1)            # two adjacent scales, 256 + 256 channels\n        return self.a(z) + self.blocks(self.b(z))\n\nup = lambda x: F.interpolate(x, scale_factor=2, mode=\"nearest\")\ndown = nn.ModuleList(nn.Conv2d(256, 256, 3, stride=2, padding=1) for _ in range(2))\nfuse = nn.ModuleList(Fusion() for _ in range(4))\n\n# Top-down: upsample F5 2x and fuse it with S4, then upsample again and fuse with S3\nT4 = fuse[0](up(F5), S4)\nT3 = fuse[1](up(T4), S3)\n# Bottom-up: downsample back, fusing with T4 and then with F5\nB4 = fuse[2](down[0](T3), T4)\nB5 = fuse[3](down[1](B4), F5)\nfor name, x in [(\"T3\", T3), (\"B4\", B4), (\"B5\", B5)]:\n    print(name, tuple(x.shape))\n\nmemory = torch.cat([x.flatten(2) for x in (T3, B4, B5)], dim=2).transpose(1, 2)\nprint(\"Encoder output\", tuple(memory.shape))\n```\n\n```text\nT3 (1, 256, 80, 80)\nB4 (1, 256, 40, 40)\nB5 (1, 256, 20, 20)\nEncoder output (1, 8400, 256)\n```\n\nT3, B4 and B5 are names chosen for the demo; the paper doesn't name the intermediate results. The output is still three levels, the same sizes as the input, all with 256 channels; flattened and concatenated, they form a sequence of 8,400 features.\n\nThis number is the same as YOLOv8's 8,400 boxes earlier, because both predict on three grids at strides 8, 16 and 32. From here the two part ways. YOLO hands the boxes from every position to NMS, while RT-DETR picks only 300 of them for the decoder.\n\n\n> [!TIP]\n> \n> CCFF's two paths and the RepBlock each have their own history; see our notes:\n> \n> - **[[18.03] PANet: Give Me a Shortcut](/blog/papers/feature-fusion/panet)**\n> - **[[21.01] RepVGG: Making VGG Great Again](/blog/papers/reparameterization/repvgg)**\n\n\n### Picking 300 Queries\n\nDETR's original queries are a set of learnable vectors that have nothing to do with the input image, and they are hard to optimize. Later methods pick them from the encoder output instead. The two-stage version of Deformable DETR and DINO both select the top K features by classification score to initialize the queries (DINO uses them only as positional queries). RT-DETR takes K = 300, uses the selected features as content queries, and uses the boxes they predict as the starting points of the positional queries.\n\nContinuing the example above:\n\n```python\nscore_head = nn.Linear(256, 80)    # COCO's 80 classes\nbox_head = nn.Linear(256, 4)\n\nlogits = score_head(memory)                       # scores for the 80 classes at each position\ntop_score, top_idx = logits.max(-1).values.topk(300, dim=1)\nidx = top_idx[..., None]\ncontent = memory.gather(1, idx.expand(-1, -1, 256))           # content queries\ninit_box = box_head(memory).sigmoid().gather(1, idx.expand(-1, -1, 4))  # initial boxes\nprint(\"Scores\", tuple(logits.shape), \"→ selected\", tuple(content.shape), \"and\", tuple(init_box.shape))\n```\n\n```text\nScores (1, 8400, 80) → selected (1, 300, 256) and (1, 300, 4)\n```\n\nBoth prediction heads in the demo have random weights. The official code also has a linear layer and a LayerNorm before the heads, and the box prediction adds each position's anchor; the selection itself is a single topk.\n\nThe trouble lies in what the selection is based on. A high classification score says that this position looks like it has an object, but it doesn't guarantee that the predicted box is accurate. A detector has to get both the class and the box location right; if only the classification score counts, poorly localized features may get selected too, and the decoder has to refine from a poor starting point.\n\nThe authors call this mismatch uncertainty, define it as the gap between the predicted distributions of localization and classification, and put it into the classification loss so that both are minimized together:\n\n$$\n\\mathcal{U}(\\hat{\\mathcal{X}}) = \\lVert \\mathcal{P}(\\hat{\\mathcal{X}}) - \\mathcal{C}(\\hat{\\mathcal{X}}) \\rVert, \\quad \\hat{\\mathcal{X}} \\in \\mathbb{R}^D\n$$\n\n$$\n\\mathcal{L}(\\hat{\\mathcal{X}}, \\hat{\\mathcal{Y}}, \\mathcal{Y}) = \\mathcal{L}_{box}(\\hat{\\mathbf{b}}, \\mathbf{b}) + \\mathcal{L}_{cls}(\\mathcal{U}(\\hat{\\mathcal{X}}), \\hat{\\mathbf{c}}, \\mathbf{c})\n$$\n\nHere $\\hat{\\mathcal{X}}$ is the encoder feature, $\\hat{\\mathbf{c}}$ and $\\hat{\\mathbf{b}}$ are the predicted class and box, and $\\mathbf{c}$ and $\\mathbf{b}$ are the annotations.\n\nThe formula is abstract; what the official code does is much more concrete. It trains the classification score with Varifocal loss. If a prediction is matched to an annotation in the Hungarian matching, its training target for that class changes from 1 to the IoU between its box and the annotated box; for unmatched predictions, the target is 0. Take three selected features as an example:\n\n| Feature | Matched annotation | IoU of predicted box and annotation | Usual classification target | RT-DETR classification target |\n| --- | --- | ---: | ---: | ---: |\n| #1 | dog | 0.45 | 1 | 0.45 |\n| #2 | cat | 0.90 | 1 | 0.90 |\n| #3 | unmatched | — | 0 | 0 |\n\n*Table: An example for this note.*\n\nFeature #1's box overlaps the dog with an IoU of only 0.45, so its classification score is pulled toward 0.45 instead of being pushed toward 1 as before. Once the classification score is trained to reflect box quality, the top 300 picked by score lean toward features whose boxes are accurate as well. This loss applies both to the 300 predictions selected from the encoder and to the output of every decoder layer.\n\n\n> [!TIP]\n> \n> If you search the official code for the name uncertainty-minimal, you won't find it. Someone asked about this on GitHub back in August 2024, and another user pointed out that it lives in the loss function `loss_labels_vfl` ([RT-DETR #438](https://github.com/lyuwenyu/RT-DETR/issues/438)). The paper's v1 called this design IoU-aware query selection, a name closer to how the code implements it.\n\n\nHow well does it work? On COCO val2017, the authors drew the features picked by the two selection methods as a scatter plot. The horizontal axis is the IoU between box and annotation and the vertical axis the classification score, with only points scoring above 0.5 drawn; purple is the new method, green the original selection by classification score, and the curves on the top and right show the point density:\n\n[![Scatter plot with IoU score from 0 to 1 on the horizontal axis and Classification score from 0.5 to 1 on the vertical axis. The purple points are Uncertainty-minimal, heavily concentrated in the upper right, with IoU around 0.6 to 0.9 and classification scores of 0.7 and above; the green points are Vanilla, fewer in number and concentrated in the lower right, with classification scores mostly between 0.5 and 0.65. In the density curves on the top and right, purple is clearly higher than green.](/content/papers/assets/420e753b3717e561d473e69a1066095c23584488dab765ae7acee273b91819f8.png)](/content/papers/assets/420e753b3717e561d473e69a1066095c23584488dab765ae7acee273b91819f8.png)\n\n*Figure 6 from the paper, Zhao et al., excerpted from [**page 6 of the v3 PDF**](https://arxiv.org/pdf/2304.08069v3#page=6). Classification scores and IoU of the encoder features picked by the two query selection methods.*\n\nThe closer a point is to the upper right, the more likely both its class and its box are correct. The purple points crowd into the upper right; the green points cluster in the lower right, with decent boxes but low classification scores, and there are far fewer of them. Table 4 turns this into proportions (RT-DETR-R50, trained for 12 epochs):\n\n| Query selection | AP | Share with classification score > 0.5 | Share with both > 0.5 |\n| --- | ---: | ---: | ---: |\n| By classification score (original) | 47.9 | 0.35% | 0.30% |\n| uncertainty-minimal | 48.7 | 0.82% | 0.67% |\n\n*Table: Table 4 of the paper.*\n\nBoth proportions more than double, and AP rises by 0.8.\n\n### The Decoder: Dropping the Last Few Layers\n\nRT-DETR's decoder copies DINO's almost wholesale, with 6 layers, 300 queries, and deformable attention for cross-attention with 4 sampling points. Training also carries over DINO's denoising exercise, and Table A in the appendix lists the denoising number as 200.\n\n\n> [!TIP]\n> \n> The denoising exercise feeds noised annotation boxes to the decoder as extra queries and asks the model to recover the original boxes; it is removed entirely at inference. The official config file says `num_denoising: 100`; the code makes a positive and a negative copy of each group, so the number of denoising queries actually sent to the decoder is around 200, varying with the image in the batch that has the most annotations. For where this approach comes from, see:\n> \n> - **[[22.03] DN-DETR: Dog Today, Cat Tomorrow](/blog/papers/object-detection/dn-detr)**\n> - **[[22.03] DINO: Close, but Not Close Enough](/blog/papers/object-detection/dino-detr)**\n\n\nEvery decoder layer is followed by its own prediction heads, and during training the output of every layer goes into the loss. So every layer produces a complete set of predictions that can be used directly. At inference, the official code uses `eval_idx` to choose which layer's output to use; the loop stops at that layer, and the layers after it never run.\n\nThe authors trained decoders with 4 to 7 layers, then looked at the results of stopping at each layer during inference (RT-DETR-R50, trained for 72 epochs):\n\n| Layers used at inference | Det4 | Det5 | Det6 | Det7 | Latency (ms) |\n| ---: | ---: | ---: | ---: | ---: | ---: |\n| 7 | | | | 52.6 | 9.6 |\n| 6 | | | 53.1 | 52.6 | 9.3 |\n| 5 | | 52.9 | 53.0 | 52.5 | 8.8 |\n| 4 | 52.7 | 52.7 | 52.7 | 52.1 | 8.3 |\n| 3 | 52.4 | 52.3 | 52.4 | 51.5 | 7.9 |\n| 2 | 51.6 | 51.3 | 51.3 | 50.6 | 7.5 |\n| 1 | 49.6 | 48.8 | 49.1 | 48.3 | 7.0 |\n\n*Table: Table 5 of the paper. Det k means the decoder was trained with k layers, and each cell is AP; the latency column depends only on how many layers inference uses.*\n\nStart with the Det6 column. Dropping from 6 layers to 5 costs only 0.1 AP and saves 0.5 ms; at 4 layers, AP is 52.7 at 8.3 ms. Each extra layer adds about 0.4 to 0.5 ms, and the later the layer, the less it helps AP.\n\nNow compare across the columns. Det6 stopped at layer 4 gives 52.7, the same as Det4 trained with 4 layers from the start; stopped at layer 5 it gives 53.0, 0.1 higher than Det5 trained with 5 layers. In this table, training a 6-layer model and truncating it works about as well as training a shallower model separately. As for 7 layers, the best it reaches is 52.6, worse than 6 layers.\n\nHow wide is the range? Using only layer 1 takes 7.0 ms, and using all 6 layers takes 9.3 ms. Answering a user on GitHub, the author mentioned that the parts of the current RT-DETR are fairly balanced, with the time going mainly to the backbone and the decoder ([RT-DETR #266, 2024-04](https://github.com/lyuwenyu/RT-DETR/issues/266)). And since the number of decoder layers can be adjusted without retraining, it amounts to an extra speed knob.\n\nThe officially released models use it this way. The scaled-down RT-DETR-R50 in Table B of the appendix halves the RepBlock channels, and stopping the same model at layers 2 through 6 ranges from 50.3 AP at 154 FPS up to 52.2 AP at 125 FPS; YOLOv8-M in the same table has 50.2 AP at 97 FPS. For RT-DETR-R50-m in the official repository (51.3 AP, 145 FPS), the config file says `eval_idx: 2`, which uses the output of layer 3.\n\n## Discussion\n\n### Against YOLO and DINO\n\nTable 2 compares RT-DETR with YOLO's L and X sizes. The data is COCO val2017; RT-DETR and YOLO both use 640×640 input, and the other DETRs use 800×1333; FPS is measured on a T4 with TensorRT FP16 at batch size 1, and YOLO uses official weights with NMS attached, following the end-to-end benchmark above:\n\n| Model | Params (M) | GFLOPs | FPS | AP | AP<sub>S</sub> |\n| --- | ---: | ---: | ---: | ---: | ---: |\n| YOLOv6-L | 59 | 150 | 99 | 52.8 | 34.4 |\n| YOLOv7-X | 71 | 189 | 45 | 52.9 | 36.9 |\n| YOLOv8-L | 43 | 165 | 71 | 52.9 | 35.3 |\n| YOLOv8-X | 68 | 257 | 50 | 53.9 | 35.7 |\n| DINO-Deformable-DETR-R50 | 47 | 279 | 5 | 50.9 | 34.6 |\n| RT-DETR-R50 | 42 | 136 | 108 | 53.1 | 34.8 |\n| RT-DETR-R101 | 76 | 259 | 74 | 54.3 | 36.0 |\n\n*Table: Excerpted from Table 2 of the paper. AP<sub>S</sub> is the AP on small objects.*\n\nA few pairs worth a look:\n\n- **RT-DETR-R50 vs. YOLOv8-L**: AP is 53.1 vs. 52.9, only 0.2 higher; speed is 108 vs. 71 FPS, or 9.3 vs. 14.1 ms per image. GFLOPs are a bit lower too, 136 vs. 165.\n- **RT-DETR-R101 vs. YOLOv8-X**: 0.4 AP higher, at 74 vs. 50 FPS.\n- **RT-DETR-R50 vs. YOLOv6-L**: only 0.3 AP higher, at 108 vs. 99 FPS, a much smaller gap.\n\nSmall objects are where RT-DETR loses. RT-DETR-R50's AP<sub>S</sub> is 34.8, 0.5 below YOLOv8-L's 35.3; R101's 36.0 is 0.9 below YOLOv7-X's 36.9. The authors list this among their limitations and call it a weakness DETRs share.\n\nThe training conditions differ too. RT-DETR's backbone is first pretrained on ImageNet, then trained on COCO for 72 epochs. The R50 weights loaded by the official code are a ResNet50-vd trained by PaddleClas with knowledge distillation (`ssld_v2`); [PaddleClas's model table](https://paddleclas-doc.readthedocs.io/zh/latest/models/ResNet_and_vd_en.html) lists its ImageNet top-1 as 83.0%, against 76.5% for the original ResNet-50. The YOLOv7 and YOLOv8 in the table, by contrast, are trained from scratch, and YOLOv10's paper states in its appendix that it trains from scratch just like YOLOv8, YOLOv7 and YOLOv9. This table compares whole systems, backbone weights and training recipes included.\n\nWith additional pretraining on Objects365 and fine-tuning on COCO, R18, R50 and R101 reach 49.2, 55.3 and 56.2 AP, which is 2.7, 2.2 and 1.9 higher than with COCO alone (Table C in the appendix).\n\nAgainst DINO, RT-DETR-R50 is 2.2 AP higher, at 108 vs. 5 FPS, about 21 times faster. This, too, is a whole-system comparison. DINO's input is 800×1333, 2.6 times the pixels of 640×640, and it trains for 36 epochs, while RT-DETR trains for 72. To see how much the hybrid encoder itself saves, go back to the matched comparison in Table 3.\n\nIn June 2024, a user on GitHub questioned this comparison ([RT-DETR #349](https://github.com/lyuwenyu/RT-DETR/issues/349)). Measuring on an RTX 3090, the user found that RT-DETR's FLOPs were about half of DINO's, consistent with the paper, yet RT-DETR ran only about twice as fast; the user also pointed out that the two use different data augmentation and backbones. The author replied that DINO's speed has to be measured under the conditions in which it reaches the paper's accuracy, that they had tested on V100, T4 and 3090 with the expected results, and that across different models, only comparing final accuracy and speed is fair. After a few rounds, each side kept its original position.\n\n### How Should the Thresholds Be Set?\n\nIn October 2023, a user asked a very practical question on GitHub ([RT-DETR #77](https://github.com/lyuwenyu/RT-DETR/issues/77)). The end-to-end benchmark uses the validation thresholds, confidence 0.001 and IoU 0.7; in production, though, people usually use a confidence threshold of around 0.1 to filter out most background boxes first, which makes NMS much faster and shrinks RT-DETR's speed advantage.\n\nThe author replied that with a 0.1 threshold, YOLO's mAP can't reach the reported number. Measuring accuracy at 0.001 and speed at 0.1 assumes two states the model can't be in at the same time; RT-DETR's score threshold only filters the output, so its speed at deployment is the same as at evaluation.\n\nBoth sides have a point. Table 1 happens to supply the middle ground, where raising the confidence threshold from 0.001 to 0.05 cuts the EfficientNMS time by 1.3 ms and AP by 1.7. On the other hand, RT-DETR's 53.1 is also computed by handing all 300 outputs per image to the evaluation code; applying a score threshold at deployment can only keep AP flat or lower it, and the difference is that its speed stays the same.\n\nWhen reading these two tables, also keep in mind that the YOLO times in Table 2 include the whole NMS plugin while Table 1 lists only one of its kernels, so the times in the two tables can't be subtracted directly.\n\n\n> [!TIP]\n> \n> A year later, YOLOv10 adopted RT-DETR's end-to-end benchmark for measuring latency, while also removing NMS from YOLO itself:\n> \n> - **[[24.05] YOLOv10: Goodbye NMS](/blog/papers/object-detection/yolov10)**\n\n\n### On Another Machine\n\nIn February 2024, another user used trtexec to compare RT-DETR-R18 with YOLOv8s plus NMS on three graphics cards ([RT-DETR #214](https://github.com/lyuwenyu/RT-DETR/issues/214)). On an RTX 4090 it was 1.065 vs. 1.90 ms, a ratio in line with the paper; on a T4, however, it was 5.6 vs. 5.4 ms, with YOLOv8s slightly faster; and on a laptop RTX 3050, RT-DETR was almost 2 ms slower.\n\nThe author replied that the paper's YOLO speed is an average over the 5,000 images of val2017, because NMS time varies with the number of boxes that pass the score threshold; also, RT-DETR uses more kinds of operators than YOLOv8, and different TensorRT versions support them to different degrees. The thread reached no conclusion. End-to-end speed depends on the hardware, the software versions and the data, so for your own use case you still have to measure it once on your own machine.\n\n### Duplicate Boxes Still Turn Up\n\nRT-DETR removed NMS, but duplicate boxes haven't disappeared entirely. In July 2024, a user reported that the same object occasionally gets several boxes, and others had also run into almost perfectly overlapping boxes with different or even identical classes ([RT-DETR #379](https://github.com/lyuwenyu/RT-DETR/issues/379)). The author suggested choosing the score threshold carefully. Another user said that the scores of these duplicates are often very close, so a threshold can't separate them; attaching NMS yourself fixes it at the cost of extra time, and the problem is rarer when the model is well trained.\n\n\n> [!NOTE]\n> \n> If you use `rtdetr-l` or `rtdetr-x` from the Ultralytics package, these are the HGNetv2-backbone versions listed in the official repository, at 53.0 AP and 114 FPS and at 54.8 AP and 74 FPS respectively, the two models the paper's v1 featured. This v3 centers instead on R50 and R101 with ResNet backbones.\n\n\n## Conclusion\n\nThe RT-DETR paper does two things. First, it measures YOLO's speed together with NMS, using the thresholds that produced the reported AP; second, it takes DETR apart to see where the time goes and where it can be saved. The takeaways are roughly these:\n\n1. **NMS time follows the thresholds**. For YOLOv8 on a T4, raising the confidence threshold from 0.001 to 0.05 cuts the EfficientNMS time from 2.36 to 1.06 ms and drops AP from 52.9 to 51.2.\n2. **Keep self-attention only in S5**. Removing the intra-scale interaction in S3 and S4 cuts latency by 35% without losing AP; with AIFI and CCFF, the encoder is 2.3 AP higher than variant C, the multi-scale Transformer encoder, with 30% less latency.\n3. **Make the classification score reflect box quality**. Using IoU as the classification target for query selection adds 0.8 AP in the 12-epoch setting.\n4. **The decoder can be truncated**. Each layer costs about 0.5 ms, and a 6-layer model stopped at layer 4 is as accurate as one trained with 4 layers from the start.\n\nNext time you read a real-time detector's speed table, first check whether NMS is included and which thresholds were used, then which card and which TensorRT version. RT-DETR's speed doesn't change with the threshold, but small-object AP and backbone pretraining belong in the comparison too.\n\nThis end-to-end benchmark was later adopted by YOLOv10, and RT-DETR itself became the starting point for later real-time DETRs. At the end of 2024, [DEIM](/blog/papers/object-detection/deim) changed how RT-DETRv2 and D-FINE are trained so that these models learn faster.\n","imageSizes":{"/content/papers/assets/3ce51df5cdcf3f7995e63085f9c6925d29364b00decdae24bb9a6f2b628bacb1.png":{"width":664,"height":508},"/content/papers/assets/8e2d050c9352772d789f19ade58cec81b5345d6cd86289b7a51014c231742ca8.png":{"width":800,"height":2044},"/content/papers/assets/7e2de3c38daff439f51d86ec04a7bd391c3f708b817ae539f3c4df7c5546f4d6.png":{"width":1360,"height":332},"/content/papers/assets/420e753b3717e561d473e69a1066095c23584488dab765ae7acee273b91819f8.png":{"width":632,"height":620}}}
