Knowledge BaseDetection & Segmentation

Object Detection

Finding *what* is in an image and *where* — taught from zero. Start with drawing a box around a dog, then build up to IoU, NMS, anchors, and the leap from R-CNN to YOLO to DETR.

advanced#yolo#detr#rcnn#bounding-box

Start here — what object detection really is

Forget the acronyms for a moment. Show a photo to an image classifier and it answers one question: "is there a dog in this picture?" — a single label for the whole image. That's useful, but it's not enough for a self-driving car, which needs to know there is a pedestrian, and they are right there, two meters ahead.

Object detection answers two questions at once, for every object in the picture:

  1. What is it? (a class label — dog, car, person)
  2. Where is it? (a box drawn tightly around it)

That second question — the where — is the whole new idea. Everything else on this page is machinery for drawing good boxes and then cleaning up the mess when the model draws too many.

How to read this page

It teaches from first principles — plain words and a hand-drawn example come before any formula. When you are ready, flip the Depth switch at the top to reveal the formal notation and the loss functions. Nothing is hidden for good; deeper material sits in the Go deeper panels for the moment you are curious.

Think of it like a librarian pointing at shelves:

An image classifier is a librarian who says yes, we have books about dogs. A detector is a librarian who walks you to each dog book and puts a finger right on its spine. Same knowledge, but now with a location attached to every single item.

The two things a detector outputs for each object

For every object it finds, a detector emits a plus a . Pinning down that box is called .

Detection = classification + a little geometry, repeated everywhere

At heart a detector reuses everything you learned about classification, but bolts on a small geometry problem: for each candidate spot in the image it answers is there an object here?, which class?, and how do I nudge a rectangle to hug it tightly? Do that across the whole image and you have detection.

What a single detection looks like

Imagine a 400×300 photo with one dog. The detector might return:

  • class: dog
  • confidence: 0.92 (it is 92% sure)
  • box: [x1, y1, x2, y2] = [50, 80, 210, 260]

Read the box as two corners: the top-left is at pixel (50, 80) and the bottom-right at (210, 260). So the dog occupies a rectangle 210 − 50 = 160 pixels wide and 260 − 80 = 180 pixels tall. That is the entire answer for one object — a label, a confidence, and four numbers.

How good is a box? Intersection over Union (IoU)

The moment you predict boxes, you need a way to score them. "Right or wrong" is too crude — a box can be almost perfect, or roughly right, or wildly off. We want one number from 0 to 1 that says how well a predicted box overlaps the true box. That number is IoU.

Think of it like two sticky notes on a window:

Slap a predicted sticky note and the true sticky note on a window. IoU asks: of the total glass the two notes cover between them, what fraction is covered by both at once? Stack them perfectly and the answer is 1. Pull them fully apart and it is 0. Half-overlapping lands somewhere in the middle.

Computing IoU by hand

Two boxes, each 100×100 pixels:

  • predicted: [50, 50, 150, 150]
  • ground truth: [80, 80, 180, 180]

Step 1 — the intersection (the shared rectangle). Its left edge is the rightmost of the two left edges, max(50, 80) = 80; its right edge is the leftmost of the two right edges, min(150, 180) = 150. Same for top/bottom. So the overlap is 80..150 wide and 80..150 tall = 70 × 70 = 4900 pixels.

Step 2 — the union (total area either box covers). Add both areas and subtract the overlap you would otherwise double-count: 10000 + 10000 − 4900 = 15100.

Step 3 — divide: IoU = 4900 / 15100 ≈ 0.325.

A rough-but-real overlap. Detectors usually count a box as correct only when IoU clears a threshold like 0.5.

Now the same idea in symbols. For a predicted box AA and a ground-truth box BB:

IoU=ABAB\text{IoU} = \frac{\lvert A \cap B \rvert}{\lvert A \cup B \rvert}
  • AA and BB are the two rectangles — the guess and the truth.
  • ABA \cap B is the intersection: the little rectangle where they overlap. The \cap symbol means "the part in both."
  • ABA \cup B is the union: all the area either one covers. The \cup symbol means "the part in either."
  • \lvert \cdot \rvert means "the area of" — literally how many pixels that region contains.
  • Why it matters: IoU is the yardstick behind almost every detection decision. It decides whether a prediction counts as a hit, and (next section) which duplicate boxes to throw away. Get comfortable with it — it reappears constantly.

Here it is as six lines of code you can run and poke at:

Python · runs in your browser
Try to recall

Why do we subtract the intersection when computing the union area, instead of just adding the two box areas?

Hint: Picture the overlapping region — how many times does it get counted if you just add?

Too many boxes: Non-Maximum Suppression (NMS)

Here is a problem you did not see coming. A detector does not politely emit one box per object — it fires off many overlapping guesses for the same dog, each slightly shifted, each with its own confidence. Left alone, your "dog detector" reports five dogs where there is one.

Think of it like a room full of people answering the same question:

Ask a crowded room where is the dog? and a dozen people point at almost the same spot, some loudly (high confidence), some hesitantly. You do not want a dozen answers. You take the most confident person's answer, then hush everyone pointing at essentially the same place — and repeat for any genuinely different spot.

That hushing procedure is , or NMS. It is the reason a well-built detector reports one box per object instead of a pile.

NMS on three boxes, step by step

Three predicted boxes with confidence scores:

  • box A [50, 50, 150, 150], score 0.90
  • box B [55, 55, 155, 155], score 0.80 (almost the same place as A)
  • box C [300, 300, 400, 400], score 0.95 (far away, a different object)

Run NMS with an IoU threshold of 0.5:

  1. Take the highest score first: C (0.95). Keep it. Nothing else overlaps C, so nothing is suppressed.
  2. Next highest: A (0.90). Keep it.
  3. Now check B against the kept boxes. B overlaps A with IoU ≈ 0.82, which is above 0.5 — B is a near-duplicate of A. Suppress B.

Final answer: keep C and A, drop B. Two objects, two boxes. Exactly right.

Python · runs in your browser
Try to recall

A detector reports the same car five times, as five heavily-overlapping boxes. Which technique collapses them to one, and which single number decides what counts as overlapping?

Hint: One is an algorithm; the other is the yardstick from the previous section.

Where do the candidate boxes come from? Anchors and box regression

We have been assuming boxes appear from somewhere. Where? Early detectors ran a classifier at every position and scale — astronomically slow. The trick that made detection practical is the anchor.

Think of it like a sheet of pre-cut stencils:

Instead of inventing every box from scratch, lay a grid over the image and, at each grid point, pre-place a handful of reference rectangles in assorted sizes and shapes — tall, wide, small, large. These stencils are guesses at where objects might be. The network then only has to (a) say which stencils actually contain an object and (b) nudge each chosen stencil a little to fit snugly. Correcting a nearby guess is far easier than conjuring a box from nothing.

Each of those pre-placed reference rectangles is an . The network never outputs raw pixel coordinates; it outputs small offsets that stretch and shift the anchor onto the object. Learning a gentle correction is much more stable than regressing absolute positions.

Two families of detectors

Two-stage (R-CNN family) — first propose promising regions, then classify and refine each one. More moving parts, higher accuracy, slower. The flagship is Faster R-CNN.

One-stage (YOLO, SSD, RetinaNet) — predict every box and class in a single forward pass over a grid. Simpler and fast enough for real time. Historically a touch less accurate; modern YOLOs have largely closed the gap.

Faster R-CNN, briefly

A slides over the CNN's feature map and proposes object regions from anchors. Each proposal is cropped to a fixed size (RoI pooling) and passed to two heads — one for the class, one to refine the box. It made region proposals learnable and end-to-end, and introduced anchors.

YOLO, briefly

YOLO (You Only Look Once) divides the image into a grid; each cell predicts a fixed number of boxes with an objectness score and class scores, all in one shot. Reframing detection as a single regression problem is what made real-time detection practical.

DETR, the modern reframing

DETR removes anchors and NMS entirely by treating detection as : a Transformer decoder emits a fixed set of object queries, each becoming at most one box, matched to the ground truth by the . Because each query is trained to claim a distinct object, there are no duplicates to suppress. It is the basis for RT-DETR and Grounding DINO.

What fundamentally distinguishes DETR from YOLO and Faster R-CNN?

Scoring a whole detector: precision, recall, and mAP

IoU scores one box. But how good is the detector overall, across a whole test set? Two familiar quantities combine into the standard metric.

A prediction is a true positive if it matches a real object (right class, IoU above threshold), a false positive if it matches nothing, and a false negative is a real object the detector missed. From these:

Precision=TPTP+FP,Recall=TPTP+FN\text{Precision} = \frac{TP}{TP + FP}, \qquad \text{Recall} = \frac{TP}{TP + FN}
  • TPTP (true positives) — correct detections. The ones you got right.
  • FPFP (false positives) — boxes that hit nothing. Hallucinated objects.
  • FNFN (false negatives) — real objects you failed to find. Misses.
  • Precision reads as "of everything I flagged, what fraction was real?" — it punishes hallucinations.
  • Recall reads as "of everything really there, what fraction did I catch?" — it punishes misses.
  • Why it matters: these two trade off. Lower the confidence bar and you catch more objects (recall up) but also invent more junk (precision down). A detector is only trustworthy if it holds both high at once.

Sweep the confidence threshold and plot precision against recall — the area under that curve is the for a class. Average it over every class (and, for COCO, over the ten IoU thresholds) and you get mAP, mean Average Precision — the number every detection paper reports. See Evaluation & Metrics.

Running a modern detector

In practice you rarely write any of this — you fine-tune a pretrained model. Deep-learning libraries like PyTorch need a real GPU, so this cell opens in Colab rather than running in your browser:

Python · needs a GPU — run on Colab
from ultralytics import YOLO

model = YOLO("yolo11n.pt")             # pretrained, tiny
results = model("street.jpg")           # inference — anchors, NMS, all handled

for box in results[0].boxes:
    cls  = model.names[int(box.cls)]
    conf = float(box.conf)
    x1, y1, x2, y2 = box.xyxy[0].tolist()
    print(f"{cls} {conf:.2f} at ({x1:.0f},{y1:.0f})-({x2:.0f},{y2:.0f})")
Common pitfalls
  • Reporting plain accuracy instead of mAP — detection needs a localization-aware metric.
  • Forgetting NMS, so every object is reported several times over.
  • Ignoring class imbalance — background dwarfs objects; Focal Loss (RetinaNet) exists precisely for this.
  • Tiny objects slipping through — use a feature pyramid (FPN) to detect across scales.

Best practices

  • Start from a pretrained detector and fine-tune on your data — almost never train from scratch.
  • Match your anchors and input resolution to the object sizes you actually care about.
  • Use strong augmentation (mosaic, mixup) — it is a big lever for detectors specifically.
  • Evaluate at multiple IoU thresholds (COCO's mAP@[.5:.95]), not just at 0.5.

Two predicted boxes for the same car overlap with IoU 0.9. Which technique removes the redundant one?

Explain it yourself

Explain to a friend, with no formulas, why a detector needs Non-Maximum Suppression at all, and how it decides which boxes to throw away. Use the crowded-room picture. If you stall on how it picks what to keep, that is the exact spot to reread the NMS section.

Recap — the key ideas
  • Object detection answers what and where for every object — a class label plus a bounding box each.
  • IoU (intersection over union) scores how well a predicted box overlaps the true box, from 0 to 1 — the yardstick behind every detection decision.
  • Detectors emit many overlapping boxes; NMS keeps the most confident and suppresses its near-duplicates, using IoU to judge overlap.
  • Anchors are pre-placed reference boxes; the network predicts small offsets to reshape them, which trains far more stably than raw coordinates.
  • Two-stage (Faster R-CNN) proposes then refines — accurate, slower. One-stage (YOLO, RetinaNet) does it in one pass — fast. DETR reframes detection as set prediction, dropping anchors and NMS.
  • mAP — built from precision and recall across confidence and IoU thresholds — is how whole detectors are compared.

Practice — and how to make it stick

Learn it the way that actually works

Three research-backed habits, built into this platform:
Retrieval practice: attempt the exercises below before rereading — pulling an answer from memory beats recognizing it on the page.
Spaced repetition: mark this topic complete and it joins your Review queue, resurfacing right before you would forget.
Interleaving: mix these with problems from CNNs and Evaluation & Metrics rather than grinding detection alone — messier practice, sturdier memory.

Start with this hands-on lab. It runs in your browser — finish the TODO so the near-duplicate box is suppressed, then check your answer against the NMS worked example above.

Python · runs in your browser

Then go deeper, roughly in order of difficulty:

  1. By hand: two boxes [0,0,10,10] and [5,5,15,15]. Compute their IoU on paper, then verify with the iou function above.
  2. From scratch: you already implemented IoU and NMS here — now compute mAP@0.5 yourself on a tiny labeled set and compare to a framework's reported number.
  3. Fine-tune: train YOLO on a small 3-class dataset you annotate (e.g. in Roboflow), and compare a one-stage vs a two-stage detector on speed and accuracy.

Next: extend boxes to pixel-precise masks in Instance Segmentation.

Key papers