PTENES
MODULE 3.3 · PRACTICE

🔍 Detect objects with YOLO26

The color mask finds “the red thing.” A detector finds the person, the bottle, the cat, with a box and a confidence score. You run Ultralytics YOLO26 on the Pi 5, export to NCNN and measure the improvement, learn about the AI HAT+, train a model with your own photos, and learn where detection fails.

6
Topics
Intermediate
Level
Practice
Type
yolo26n
Model
0%
0 of 0 topics read · Section 1 of 6

Detailed content

1

🔍 What object detection is

A object detector takes an image and returns a list: for each thing it recognizes, a box (where it is), a class (what it is), and a confidence score (from 0 to 1, how sure the model is). YOLO (“you only look once”) does this by looking at the image just once, which makes it fast enough for robots. Ultralytics’ pretrained models already recognize the 80 classes in the COCO dataset, such as person, car, dog, bottle, and chair.

🌱 New here?

A neural network is a program with millions of adjustable numbers (the weights) that learns patterns from examples. Training means adjusting those weights by showing the model thousands of labeled images. Inference is to use the ready-made model on a new image, which is what the robot does. The file yolo26n.pt stores these weights; “n” stands for nano, the smallest and fastest version.

person 0.91 bottle 0.67 what the code receives class: person conf: 0.91 xyxy: 90,62, 172,222 + one line per object illustrative scene · box = (x1, y1) top corner, (x2, y2) bottom corner

How to read this map: each colored box is a detected object, with a “class confidence” label. The purple panel on the right shows what reaches your program for the person: numbers only. The bottle has lower confidence (0,67) because it is small and partly in shadow; that’s where errors arise (topic 6).

🏷️ Classification

“This photo has a cat.” One answer per image, without saying where.

📦 Detection

“Cat here, person there.” Box + class + confidence. That’s what the robot needs to aim.

✂️ Segmentation

The exact outline, pixel by pixel. More precise and more demanding; useful for picking up objects with the arm.

Why learn this

The color mask fails with objects that have common colors or when the lighting changes. The detector recognizes shape, so it can follow a person wearing a shirt of any color. In return, it uses much more processing power. Knowing what each output means lets you use it to control the robot.

Key concepts

Box (bbox)
x1, y1, x2, y2
Class
what it is (80 in COCO)
Confidence
0 a 1
Inference
use the ready-made model
2

🚀 YOLO26 on Pi 5 with Ultralytics

O YOLO26 is the current generation of the Ultralytics YOLO family, the successor to YOLO11. Tutorials using older versions are still around, but today’s approach is the ultralytics with the yolo26n.ptweights n, s, m, l e x. It comes in n: each step up is a little more accurate and runs much more slowly. On the Pi 5, always start with the

n s m l x . In PyTorch, with a 640 px image, it takes about 130 ms per frame, or at most around 7 frames per second. Pi 5: start here higher = more accurate and slowerfast

How to read this map: Each step is a YOLO26 size. The highlighted "n" is the only one that keeps the robot responsive in real time using just the Pi's processor. The larger ones are useful for training comparisons on a PC or running with an accelerator.

Goal: each step is a YOLO26 size. The highlighted “n” is the only one that keeps the robot responding in time using just the Pi’s processor. Larger ones are useful for training comparisons on a PC or running with an accelerator.

Pi terminal
source ~/robo-venv/bin/activate
pip install ultralytics                        # also installs PyTorch for ARM
yolo predict model=yolo26n.pt source="https://ultralytics.com/images/bus.jpg"   # quick test
~/robo/yolo_camera.py
# YOLO26 live on the Camera Module 3: prints what it sees and the time for each frame
import sys, time
from picamera2 import Picamera2
from ultralytics import YOLO

MODELO = sys.argv[1] if len(sys.argv) > 1 else "yolo26n.pt"   # switch to NCNN in topic 3
modelo = YOLO(MODELO)

picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration(main={"size": (640, 480), "format": "RGB888"}))
picam2.start(); time.sleep(1)
print(f"Model {MODELO} loaded. Press Ctrl+C to exit.")
try:
    while True:
        quadro = picam2.capture_array()                 # BGR, as expected by Ultralytics
        t0 = time.perf_counter()
        r = modelo(quadro, imgsz=640, conf=0.5, verbose=False)[0]
        ms = (time.perf_counter() - t0) * 1000
        achados = [f"{r.names[int(c)]} {float(p):.2f}" for c, p in zip(r.boxes.cls, r.boxes.conf)]
        print(f"{ms:6.0f} ms | {1000 / ms:4.1f} FPS | {', '.join(achados) or 'nothing'}")
except KeyboardInterrupt:
    picam2.stop()

How to check

  • ✓The bus test creates a folder runs/detect/predict with the marked-up photo (bus, person).
  • ✓Live, you appear as person 0.8x and the time is around 100–200 ms per frame.
  • ✗“Illegal instruction” or a PyTorch error? Check that the system is 64-bit (uname -m = aarch64) and the venv is active.

💡 First run takes longer

The first time, Ultralytics downloads the weights yolo26n.pt from the internet, and the first frame takes much longer than the ones that follow. Measure the speed only after about ten frames.

Why learn this

With about twenty lines, you have a robot that recognizes people and everyday objects. This same loop (capture, infer, read the boxes) is the basis for project 3.6 and appears again in Track 5, when the arm needs to find an object before picking it up.

Key concepts

ultralytics
YOLO26 package
yolo26n.pt
nano weights
conf=0.5
confidence threshold
r.boxes
boxes, classes, confidence
3

⚡ Export to NCNN and measure speed

The .pt format is great for training, but it isn’t the fastest for running on an ARM processor. Ultralytics exports the same model to other formats; according to the official Raspberry Pi guide, NCNN is fastest on the Pi’s CPU. The boxes and classes stay the same; only the “engine” doing the calculations changes. The other way to improve speed is to change the input size: imgsz=320 processes a quarter of the pixels of 640, but loses accuracy on small objects.

🌱 New here?

NCNN is an open inference engine designed for phones and ARM boards. Export means converting the weights from one format to another without retraining. The imgsz is the size to which the image is resized before entering the network; it must be a multiple of 32 (320, 416, 640).

PyTorch .pt · 640~130 ms NCNN · 640lower: measure yours NCNN · 320even lower time per frame (shorter bar = better) · illustrative, except for the PyTorch reference value

How to read this map: only the top bar has a reference number (from the Ultralytics guide for the Pi 5). The others show the direction of the improvement; find the exact time by running the script below on your Pi, with your cooler and camera.

Goal: export yolo26n to NCNN and compare the two formats on the same image, with numbers.

Pi terminal
cd ~/robo && source ~/robo-venv/bin/activate
yolo export model=yolo26n.pt format=ncnn       # creates the yolo26n_ncnn_model/ folder
python yolo_camera.py yolo26n_ncnn_model       # the same script from topic 2, now using NCNN
~/robo/compara.py
# Compares PyTorch vs. NCNN (640 and 320) on the same image: average of 20 inferences
import time
from ultralytics import YOLO

IMAGEM = "https://ultralytics.com/images/bus.jpg"   # or the path to one of your photos
testes = [("yolo26n.pt", 640), ("yolo26n_ncnn_model", 640), ("yolo26n_ncnn_model", 320)]

for caminho, tamanho in testes:
    modelo = YOLO(caminho, task="detect")
    for _ in range(3):                              # warm-up: not counted
        modelo(IMAGEM, imgsz=tamanho, verbose=False)
    tempos = []
    for _ in range(20):
        r = modelo(IMAGEM, imgsz=tamanho, verbose=False)[0]
        tempos.append(r.speed["inference"])           # ms, network only
    media = sum(tempos) / len(tempos)
    print(f"{caminho:22s} imgsz={tamanho}: {media:6.1f} ms  ({1000 / media:4.1f} FPS)  objects={len(r.boxes)}")

How to check

  • ✓The folder yolo26n_ncnn_model/ is created, and the script prints three lines.
  • ✓The NCNN 640 line has a shorter runtime than the .pt line, with a similar number of objects.
  • ✓At 320, the runtime drops further, but small objects (the people in the background) may disappear.

✓ Do

  • ✓Export on the Pi itself and keep the NCNN folder alongside the code.
  • ✓Measure after warm-up with the cooler running.
  • ✓Choose the imgsz based on the size of the object that matters.

✗ Don't

  • ✗Compare formats using the first frame (including model loading).
  • ✗Switch to a larger model before you run out of options with NCNN and imgsz.
  • ✗Trusting FPS figures from online videos: measure on your Pi.

Why learn this

Doubling the FPS at no extra cost is the difference between a robot that follows a person and one that loses them at every turn. The habit of measuring before and after applies to any optimization you make from here on.

Key concepts

NCNN
faster on the ARM CPU
export
converts without training
imgsz
multiple of 32
Warm-up
ignore the first ones
4

🧩 Speed things up with AI HAT+ (Hailo)

When NCNN and imgsz aren’t enough, the next step is to move the neural network off the processor. The AI HAT+ is a board that fits on top of the Pi 5 and connects through the PCIeconnector; it has a Hailo chip designed specifically for inference. There are two generations: AI HAT+ with Hailo-8L (13 TOPS) or Hailo-8 (26 TOPS), designed for vision, and AI HAT+ 2 with Hailo-10H (40 TOPS in INT4) and 8 GB of its own memory, which can also run small language and vision-language models. Both work only with the Pi 5; the old "AI Kit" has been discontinued.

🌱 New here?

A NPU (neural processing unit) is a chip specialized in neural network calculations. TOPS These are trillions of operations per second: they give you an idea of processing capacity, but are useful only for comparing similar chips. INT4/INT8 means the model’s numbers are stored using fewer bits; this makes everything faster, with a small loss in accuracy. The model needs to be compiled for the chip’s format (for Hailo, .hef files).

CPU only captureneural network (heavy)reads boxes, decidesCPU maxed out, hot with AI HAT+ capturereads boxesCPU with room to spare NPUHailo PCIe the model needs to be compiled for the chip (.hef)

How to read this map: On the left, the CPU handles all three tasks, and the middle one (red) dominates. On the right, the heavy processing runs on the NPU over PCIe, and only the result comes back. The CPU stays free for the rest of the robot: video server, communication with the ESP32, logs.

OptionPurposeCost and effort
CPU + NCNNGet started; follow one person at a slow paceZero; just export
AI HAT+ (Hailo-8L/8)Real-time detection, multiple objectsExtra board; model compiled for Hailo
AI HAT+ 2 (Hailo-10H)Vision + small language models (Track 5)About US$ 130 at US retailers (2026); check availability in Brazil
AI Camera (Sony IMX500)Inference inside the camera itselfSpecific camera; models in its format

Step by step (overview)

1

Assemble with the Pi turned off

Connect the PCIe ribbon cable, spacers, and board on top of the Pi 5. The active cooler stays underneath.

2

Install the software listed in the docs

Update the system and install the Hailo packages for your exact board model, following the "AI" page in the official Raspberry Pi documentation. Package names vary between generations: copy them from there, not from an old tutorial.

3

Check it and run a ready-made example

Check the board with the command below and run the detection examples from the docs. Your own models need to be compiled to .hef with Hailo’s tools on a PC.

Pi terminal
lspci | grep -i hailo        # Does the board show up on the PCIe bus?
vcgencmd get_throttled       # 0x0: the power supply can handle the Pi + HAT + camera setup

How to check

  • ✓O lspci shows a line with "Hailo"; if it doesn’t, check the PCIe cable and connection.
  • ✓The detection example in the docs runs at a much higher FPS than your CPU test.

Why learn this

An accelerator isn’t required for this track: project 3.6 works with CPU and NCNN. But knowing when it’s worthwhile (many objects, high FPS, language AI on the same robot) helps you avoid buying one too early or pushing the CPU for too long.

Key concepts

NPU
inference-only chip
PCIe
fast connection to the Pi 5
TOPS
approximate capacity
.hef
Hailo-compiled model
5

🏷️ Train with your own images

COCO doesn’t include "my mug," "orange track cone," or "competition part." For that, you do a fine-tune: start with yolo26n, which already knows how to recognize shapes, and show it a few hundred of your photos with the boxes marked. Training runs on a PC with an NVIDIA GPU or in Google Colab (free GPU in your browser); the Pi only receives the finished result. Training on the Pi can work, but it’s far too slow to be worthwhile.

🌱 New here?

Labeling means drawing a box around each object in each photo and assigning it a class. The collection of labeled photos is the dataset; it’s split into training (the model learns from these) and validation (photos the model has never seen, used to measure whether it has really learned). An epoch is one complete pass through all the training photos.

1 take photosin the actual location 2 labelbox + class 3 trainPC or Colab 4 on the Pibest.pt → NCNN errors during testing become new photos: the dataset grows where the model fails

How to read this map: The purple steps happen outside the robot; the cyan step is the robot using the model. The dashed loop is the key: the first model always fails in some cases, and each error you photograph and label improves the next training run.

Step by step

1

Take photos with the robot’s camera

Start with 150 to 300 photos per class, taken with the Camera Module 3 itself in the place and lighting where the robot will work: close up, far away, from the side, partially hidden, and against different backgrounds.

2

Label and export in YOLO format

Use a labeling tool such as Label Studio, CVAT, or Roboflow and export in YOLO format: one images folder and one .txt file per image, with one line per object (class, center x, center y, width, height, all from 0 to 1). Set aside about 20% for validation.

3

Train, transfer best.pt, and export

Run the training below on your PC or in Colab, then copy best.pt to the Pi with scp and export to NCNN as in topic 3.

Goal: describe the dataset and train a two-class detector starting from yolo26n. Replace the path and class names with yours.

my_dataset/data.yaml
# Expected structure:
#   my_dataset/images/train/*.jpg   my_dataset/labels/train/*.txt
#   my_dataset/images/val/*.jpg     my_dataset/labels/val/*.txt
path: /caminho/para/meu_dataset
train: images/train
val: images/val
names:
  0: caneca
  1: cone
on a PC with a GPU or in a Colab cell
pip install ultralytics
yolo detect train data=meu_dataset/data.yaml model=yolo26n.pt epochs=100 imgsz=640 batch=16
# at the end: runs/detect/train/weights/best.pt  (the best model on validation)
yolo detect val model=runs/detect/train/weights/best.pt data=meu_dataset/data.yaml

# then, on the Pi:
# scp best.pt <your_username>@robo.local:~/robo/
# yolo export model=best.pt format=ncnn   →   python yolo_camera.py best_ncnn_model

How to check

  • ✓O val shows the mAP50 metric for each class; above 0.8 is a good starting point for simple objects.
  • ✓On the Pi, the yolo_camera.py with your model prints "mug" and "cone" live.
  • ✗A high training score but errors on the robot? Your validation photos were too similar to the training photos: take photos on a different day and in a different place.

Why learn this

This is where the robot's vision starts serving your project, instead of the other way around: competitions, sorting parts, a robot that searches for a specific object. And the process (collect, label, train, test, repeat) is the same one you use in Track 5 to teach the arm through demonstrations.

Key concepts

Fine-tuning
starts from yolo26n
Training / validation
learns / measures
data.yaml
folders and classes
best.pt
the best model
6

⚠️ Limitations: lighting, distance, false positives

A detector doesn't "see" the way you do: it makes a statistical guess for every frame. In low light, the object looks dark and blurry; far away, it takes up few pixels after resizing; and sometimes a backpack becomes a "person" for one frame. The confidence threshold is the control you can adjust: too high and the robot misses the target; too low and it chases ghosts. That's why the robot's code never reacts to just one frame.

🌱 New here?

A false positive is when the model finds something that isn't there. A false negative is when it fails to find something that is there. Lowering the threshold trades false negatives for false positives, while raising it does the opposite: there's no value that eliminates both. Persistence means requiring the object to appear in several consecutive frames before acting.

00,4 a 0,61 low thresholdchases ghosts(false positives) start here+ 3 consecutive framesbefore acting high thresholdmisses the target(false negatives) tune it for your object, lighting, and working distance

How to read this map: the scale shows the value of conf. On the left (red), the robot reacts to everything; on the right (cyan), only to very clear objects. The purple frame is a reasonable starting point, and it becomes much more stable when you require the object to appear in a few consecutive frames.

Goal: turn raw detections into a stable decision: only the class that matters, only boxes large enough, and only after 3 consecutive frames. The result is the horizontal error, just like in module 3.2.

~/robo/alvo_estavel.py
# Stable decision from YOLO26: class, minimum size, and persistence
import time
from picamera2 import Picamera2
from ultralytics import YOLO

ALVO = "person"          # class name in the model (COCO uses English names)
CONF_MIN = 0.5
AREA_MIN = 0.02          # box covers at least 2% of the image
QUADROS_SEGUIDOS = 3
LARGURA, ALTURA = 640, 480

modelo = YOLO("yolo26n_ncnn_model", task="detect")
picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration(main={"size": (LARGURA, ALTURA), "format": "RGB888"}))
picam2.start(); time.sleep(1)
contador = 0
try:
    while True:
        r = modelo(picam2.capture_array(), imgsz=640, conf=CONF_MIN, verbose=False)[0]
        melhor = None
        for (x1, y1, x2, y2), c in zip(r.boxes.xyxy.tolist(), r.boxes.cls.tolist()):
            area = (x2 - x1) * (y2 - y1) / (LARGURA * ALTURA)
            if r.names[int(c)] == ALVO and area >= AREA_MIN:
                if melhor is None or area > melhor[1]:
                    melhor = ((x1 + x2) / 2, area)          # center x and size
        contador = contador + 1 if melhor else 0
        if contador >= QUADROS_SEGUIDOS:
            cx, area = melhor
            print(f"STABLE TARGET  error={cx - LARGURA / 2:+5.0f}  size={area:.2f}")
        else:
            print(f"no stable target ({contador}/{QUADROS_SEGUIDOS}) → robot stopped")
except KeyboardInterrupt:
    picam2.stop()

How to check

  • ✓When you step in front of the camera, you see 1/3, 2/3, and then "STABLE TARGET," with the error changing sign as you move.
  • ✓A false detection in just one frame never becomes a "STABLE TARGET."
  • ✗Does it disappear when you move a few meters away? Lower AREA_MIN or accept that this is the useful range of your camera.

✓ Do

  • ✓The robot stops when it loses the target instead of continuing with the last command.
  • ✓The ultrasonic sensor or bumper stays active to prevent collisions.
  • ✓Test in the morning, afternoon, and at night.

✗ Don't

  • ✗Rely only on the camera to stop before a person or a staircase.
  • ✗React to a single frame with high confidence.
  • ✗Film or follow people without their knowledge and consent.

Why learn this

A person-following robot is the track's project, and it's only safe if you know where vision fails. Threshold, minimum size, persistence, and stopping when the target is lost are the four safeguards that separate a nice-looking demo from a robot you can trust.

Key concepts

False positive
finds what isn't there
False negative
misses what is there
Threshold
trades one for the other
Persistence
N consecutive frames

✅ Module summary

✓
Detection = box + class + confidence, for each object, in every frame.
✓
YOLO26n on Pi 5: pip install ultralytics in the venv and twenty lines with picamera2.
✓
NCNN and imgsz: the free speed boost, always measured after warm-up.
✓
AI HAT+ when needed: Hailo NPU over PCIe; the AI HAT+ 2 also runs small language models.
✓
Your model, your limits: fine-tune on a PC/Colab and make stable decisions with thresholds, size and persistence.

To go further

Next module

3.4 · AI inside the microcontroller: small, quantized models running on the ESP32-S3 itself.