Ultralytics YOLO27:
Lessonintermediate

Pick the Task and Plan the Pipeline

Map each product question to one of the seven Ultralytics YOLO tasks, with its weights, result field, label format, and gating metric, and prove the plan by running every task on one image.

Segmentation, pose, oriented bounding box and classification examples side by side

Once a detector ships, the next requests are rarely "more boxes". They are "how big is the spill", "is the worker's back bent", "which way is the ship pointing", and "is this part scrap". On the street photo used throughout this course, the bus's bounding box claims 48% of the frame while the bus itself covers 29%, so a box-based area answer would be wrong by more than half. The task you pick decides the label format, so choosing it before anyone labels is the cheapest decision in the project; changing it later means relabeling.

Outcome

Write a task plan that names the task, weights, label format, result field, and gating metric for every model in your pipeline, and confirm the result field by running all seven tasks on one image.

Fast Track
If you already know your way around, here's the short version.
  1. Rewrite the request as the question the output must answer: what kind, where, what shape, which pixels, which joints, which way, or how far.

  2. Walk the decision chart and stop at the first task whose output answers that question.

  3. Record the weights, label format, result field, and gating metric in a plan table.

  4. Add a second model only when one task cannot answer the question, and budget what it costs.

Hands-on

One photo, four different answers#

Ultralytics YOLO task outputs side by side on example images: detect, pose, segment, classify, OBB, semantic segmentation, and depth

Ask one question of one photo — how much of this frame is bus, and how far away is it? — and let four Ultralytics YOLO tasks answer it:

from ultralytics import YOLO

image = "https://ultralytics.com/images/bus.jpg"
det = YOLO("yolo26n.pt")(image, verbose=False)[0]
seg = YOLO("yolo26n-seg.pt")(image, retina_masks=True, verbose=False)[0]
sem = YOLO("yolo26n-sem.pt")(image, verbose=False)[0]
depth = YOLO("yolo26n-depth.pt")(image, verbose=False)[0]
frame = det.orig_shape[0] * det.orig_shape[1]  # pixels in the photo

i = [det.names[int(c)] for c in det.boxes.cls].index("bus")
x1, y1, x2, y2 = det.boxes.xyxy[i].tolist()
print(f"detect    bus box covers   {(x2 - x1) * (y2 - y1) / frame:.1%} of the frame")

i = [seg.names[int(c)] for c in seg.boxes.cls].index("bus")
bus_mask = seg.masks.data[i].bool()  # H x W, True on bus pixels
print(f"segment   bus mask covers  {bus_mask.sum().item() / frame:.1%} of the frame")

ratios = {row["name"]: row["pixel_ratio"] for row in sem.summary()}
print(f"semantic  'train' pixels   {ratios['train']:.1%} of the frame")

meters = depth.depth.data[bus_mask].median().item()  # depth map and mask share the original size
print(f"depth     bus is about     {meters:.1f} m from the camera")
detect    bus box covers   47.7% of the frame
segment   bus mask covers  29.2% of the frame
semantic  'train' pixels   30.9% of the frame
depth     bus is about     4.5 m from the camera

Read it line by line:

  • detect answers where. The box also contains the road under the bus and the four people standing in front of it, so as an area it is 63% too large.
  • segment answers what shape. 29.2% is the bus's real footprint in the image, the number to use for any area, coverage, or overlap rule.
  • semantic answers which pixels belong to which class. The area is close to the mask's, but the model calls the bus train: it labels surfaces with the classes of its training set (Cityscapes, lesson 4) and never separates one vehicle from another.
  • depth answers how far. The median depth inside the bus mask is 4.5 m — two tasks combined to answer a question neither answers alone.
Decision rule

If the number your product reports is an area, a coverage share, or an overlap, a box is the wrong instrument. Use a mask (segment) for objects or a class map (semantic) for surfaces.

The seven tasks at a glance#

Computer Vision Foundations covers how to choose between tasks in detail — revisit The Seven Vision Tasks if the choice is not obvious. This is the working recap for the rest of the course. Every row is a task the installed ultralytics package trains, validates, predicts, and exports with the same API; the tasks overview is the full reference.

Question the output answersTaskYOLO26 weightsResult fieldLabel formatGating metric
Where is each object?detectyolo26n.ptboxesclass + boxbox mAP50-95
What exact shape and area is each object?segmentyolo26n-seg.ptmasks + boxesclass + polygonmask mAP50-95
Which class does every pixel belong to?semanticyolo26n-sem.ptsemantic_maskPNG class map or polygonsmIoU
Where are the joints or landmarks?poseyolo26n-pose.ptkeypoints + boxesclass + box + keypointspose mAP50-95 (OKS)
How is each object rotated?obbyolo26n-obb.ptobbclass + 4 cornersOBB mAP50-95
What is this whole image (or crop)?classifyyolo26n-cls.ptprobsone folder per classtop-1 accuracy
How far from the camera is every pixel?depthyolo26n-depth.ptdepthdepth map per image (16-bit PNG or NPY)δ1 (delta1)

You already ship the first row. Lessons 2 to 8 teach the five middle rows, and lessons 9 and 10 chain and ship them. The last row, monocular depth estimation, predicts a distance in meters for every pixel of a single image. Its labels come from depth sensors or 3D renderers rather than annotators, so it has its own dataset format; this course includes it wherever the workflow is shared: this plan, the validation loop, and the export check in the last lesson.

Choose one question at a time#

Walk the questions in order and stop at the first yes:

The chart covers the common cases. Four tie-breakers cover most of the rest:

If the request…ChooseBecause
needs a count and an area ("how many spills, and how big")segmentsemantic merges touching objects into one region
involves long, thin objects packed side by side, seen from aboveobbaxis-aligned boxes overlap and NMS drops true objects, even if you never read the angle
needs front versus back, or left versus rightposean OBB gives an axis, not a heading
sees exactly one item per image by construction (a fixed inspection station)classifythe cheapest labels and the fastest model

The task is fixed when you create the dataset — on Ultralytics Platform it is the Task Type field of the New Dataset dialog — so this choice comes before the first label:

Ultralytics Platform New Dataset dialog with the upload area, dataset name, URL, and description, and the Task Type selector beside License, Blur faces, and Visibility

One API, seven result fields#

Every task uses the same call; the model reads its task from the weights file. What changes is which field of the result comes back filled, and that field is what your code will read:

from ultralytics import YOLO

WEIGHTS = ["yolo26n.pt", "yolo26n-seg.pt", "yolo26n-sem.pt", "yolo26n-pose.pt", "yolo26n-obb.pt", "yolo26n-cls.pt", "yolo26n-depth.pt"]
FIELDS = ("boxes", "masks", "semantic_mask", "keypoints", "obb", "probs", "depth")

for weights in WEIGHTS:
    model = YOLO(weights)
    result = model("https://ultralytics.com/images/bus.jpg", verbose=False)[0]
    fields = [f for f in FIELDS if getattr(result, f) is not None]
    print(f"{weights:17s} task={model.task:9s} fields={fields}")
yolo26n.pt        task=detect    fields=['boxes']
yolo26n-seg.pt    task=segment   fields=['boxes', 'masks']
yolo26n-sem.pt    task=semantic  fields=['semantic_mask']
yolo26n-pose.pt   task=pose      fields=['boxes', 'keypoints']
yolo26n-obb.pt    task=obb       fields=['obb']
yolo26n-cls.pt    task=classify  fields=['probs']
yolo26n-depth.pt  task=depth     fields=['depth']

Segment and pose results keep boxes, so detection code you already have keeps working on them. Classify, semantic, and depth results describe the whole image and have no per-object fields at all.

OBB results have no boxes

Detection code that loops over result.boxes stops with TypeError: 'NoneType' object is not iterable on an OBB model: result.boxes is None, and the rotated detections live only in result.obb. Port detection code to OBB by reading result.obb, not by guarding against None and getting zero detections.

When one model is not enough#

Most production systems that go beyond detection take one of three shapes:

  • Detect, then classify. The detector finds small objects in a large frame; an image classifier makes a fine-grained call on each full-resolution crop: helmet type, defect grade, product SKU.
  • Pose plus tracking. Keypoints describe one frame; a tracker turns them into a per-person time series you can count repetitions or detect falls from.
  • Segment, then measure. The model returns pixels; plain code turns them into areas, widths, coverage ratios, or (with depth) distances.

The labels behind a segment-then-measure pipeline are one polygon per object, like these parcels on warehouse robots in the Ultralytics Platform editor:

Ultralytics Platform annotation editor in Draw mode, with pink polygon masks traced around parcels on warehouse robots and the class list open

Every stage multiplies cost

A second model adds inference latency, a second dataset to label and maintain, and a second model to monitor. Chain only when one task cannot answer the question — a one-model plan you can ship beats a three-model plan you cannot label.

Pitfalls#

Choosing by demo appeal

Symptom: the team labels polygons because masks demo well, then the product only ever reads a count. Fix: before labeling, name the line of code that consumes the output. If nothing reads the outline, ship a detector: boxes are faster to label and faster to run.

Planning without the result field

Symptom: after a month of labeling, someone notices the product needs a heading and the dataset has OBB labels, which only give an axis. Fix: write the exact attribute into the plan (result.masks.xy, result.keypoints.xy, result.obb.xywhr) and run tasks.py with your chosen weights before the first label.

A second stage trained on the wrong images

Symptom: a classifier that scores 95% on clean product photos is wrong on most detector crops in production. Fix: build the second-stage dataset from the first stage's own crops, with their real blur and framing; lesson 9 shows how.

Try It

Take one feature request from your backlog — or use "flag pallets that overhang the rack edge on a fixed warehouse camera" — and write a plan table with these rows: question, task, weights, label format, result field, gating metric, and second stage (or "none", with the reason). Then run tasks.py and confirm the field you named comes back filled.

Done When
You've finished the lesson when all of these are true.
  • Your plan table names the task, weights, label format, result field, and gating metric for each model.

  • You can say in one sentence why a cheaper task (detect or classify) would not answer the question.

  • tasks.py ran, and the result field in your plan appears in its output.

Show solution

For the pallet request:

RowChoice
QuestionDoes any part of a pallet extend past the rack beam line?
Tasksegment — overhang depends on the pallet's outline; its box also covers the gap under the pallet and the load on top
Weightsyolo26n-seg.pt, fine-tuned on frames from the warehouse cameras
Label formatOne polygon per pallet
Result fieldresult.masks.data with retina_masks=True (pixels past the beam line)
Gating metricMask mAP50-95 on a camera held out of training
Second stageNone — the beam line is fixed per camera, so it is configuration, not a model

The overhang rule is then three lines of code: draw the beam line once per camera, count mask pixels on the wrong side of it, and alert above a pixel threshold you calibrate on a few known overhangs. Lesson 3 shows exactly this kind of mask-versus-region test.

What's next

Next, we label and train an instance segmentation model, check its polygons in code, and read what its two sets of metrics are telling us.