Complete Ultralytics Tutorial: Object Detection with YOLO
Ultralytics is a Python framework that provides state-of-the-art implementations for YOLO (You Only Look Once), one of the most popular and efficient object detection algorithms. In this tutorial, we will learn how to use Ultralytics from installation to custom model deployment.
What is Ultralytics and YOLO?
YOLO is a real-time object detection algorithm that can detect multiple objects in a single forward pass of a neural network. Ultralytics provides implementations of YOLOv8, YOLOv9, YOLOv10, and YOLO11 that are easy to use with high performance.
Ultralytics Advantages:- Very simple and intuitive API
- Support for multiple tasks: detection, segmentation, classification, pose estimation
- Pretrained models for various use cases
- Easy training and finetuning
- Export to various formats (ONNX, TensorRT, CoreML, etc.)
Installation
1. Setup Environment
# Create virtual environment
python -m venv ultralyticsenv
source ultralyticsenv/bin/activate # Linux/Mac
ultralyticsenv\Scripts\activate # Windows
Install Ultralytics
pip install ultralytics
For GPU support (CUDA)
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
2. Verify Installation
import ultralytics
from ultralytics import YOLO
Check version
print(f"Ultralytics version: {ultralytics.version}")
Check CUDA availability
import torch
print(f"CUDA available: {torch.cuda.isavailable()}")
if torch.cuda.isavailable():
print(f"GPU: {torch.cuda.getdevicename(0)}")
Quick Start: Object Detection
1. Load Pretrained Model
from ultralytics import YOLO
Load YOLOv8 model (available: yolov8n, yolov8s, yolov8m, yolov8l, yolov8x)
n=nano, s=small, m=medium, l=large, x=extra large
model = YOLO('yolov8n.pt') # Model is automatically downloaded
Or load YOLO11 (latest)
model = YOLO('yolo11n.pt')
Model Options:
| Model | Size | mAP | Speed (ms) | Use Case |
|-------|------|-----|------------|----------|
| yolov8n | 3.2M | 37.3 | 1.2 | Edge devices, real-time |
| yolov8s | 11.2M | 44.9 | 1.9 | Balance speed/accuracy |
| yolov8m | 25.9M | 50.2 | 4.1 | General purpose |
| yolov8l | 43.7M | 52.9 | 6.8 | High accuracy |
| yolov8x | 68.2M | 53.9 | 10.8 | Maximum accuracy |
2. Inference on Images
from ultralytics import YOLO
Load model
model = YOLO('yolov8n.pt')
Inference on single image
results = model('path/to/image.jpg')
Inference on multiple images
results = model(['image1.jpg', 'image2.jpg', 'image3.jpg'])
Inference from URL
results = model('https://example.com/image.jpg')
Process results
for result in results:
# Bounding boxes
boxes = result.boxes
print(f"Detected {len(boxes)} objects")
for box in boxes:
# Box coordinates (x1, y1, x2, y2)
xyxy = box.xyxy[0].tolist()
# Confidence score
confidence = box.conf[0].item()
# Class ID and name
classid = int(box.cls[0].item())
classname = model.names[classid]
print(f" {classname}: {confidence:.2f} at {xyxy}")
3. Inference on Video
from ultralytics import YOLO
import cv2
model = YOLO('yolov8n.pt')
Inference on video file
results = model('path/to/video.mp4', stream=True)
for result in results:
# Process each frame
annotatedframe = result.plot()
# Display (optional)
cv2.imshow('Detection', annotatedframe)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
4. Real-time Inference from Webcam
from ultralytics import YOLO
import cv2
model = YOLO('yolov8n.pt')
Open webcam
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# Run inference
results = model(frame, verbose=False)
# Visualize results
annotatedframe = results[0].plot()
# Display FPS
fps = 1000 / results[0].speed['inference']
cv2.putText(annotatedframe, f'FPS: {fps:.1f}', (10, 30),
cv2.FONTHERSHEYSIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow('YOLOv8 Detection', annotatedframe)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Supported Tasks
1. Object Detection
from ultralytics import YOLO
model = YOLO('yolov8n.pt')
results = model('image.jpg')
Access detections
for box in results[0].boxes:
print(f"Class: {model.names[int(box.cls)]}")
print(f"Confidence: {box.conf.item():.2f}")
print(f"Box: {box.xyxy[0].tolist()}")
2. Instance Segmentation
from ultralytics import YOLO
Load segmentation model
model = YOLO('yolov8n-seg.pt')
results = model('image.jpg')
Access masks
for result in results:
if result.masks is not None:
masks = result.masks.data # Tensor of masks
for i, mask in enumerate(masks):
print(f"Mask {i} shape: {mask.shape}")
3. Image Classification
from ultralytics import YOLO
Load classification model
model = YOLO('yolov8n-cls.pt')
results = model('image.jpg')
Access predictions
for result in results:
probs = result.probs
top5indices = probs.top5
top5conf = probs.top5conf
print("Top 5 predictions:")
for idx, conf in zip(top5indices, top5conf):
print(f" {model.names[idx]}: {conf:.2f}")
4. Pose Estimation
from ultralytics import YOLO
Load pose model
model = YOLO('yolov8n-pose.pt')
results = model('image.jpg')
Access keypoints
for result in results:
if result.keypoints is not None:
keypoints = result.keypoints.data # Shape: (numpersons, 17, 3)
for personkpts in keypoints:
print(f"Person keypoints shape: {personkpts.shape}")
# 17 keypoints: nose, eyes, ears, shoulders, elbows, wrists,
# hips, knees, ankles
5. Oriented Bounding Box (OBB)
from ultralytics import YOLO
Load OBB model (for rotated objects)
model = YOLO('yolov8n-obb.pt')
results = model('aerialimage.jpg')
Access oriented boxes
for result in results:
if result.obb is not None:
for obb in result.obb:
# xcenter, ycenter, width, height, rotation
print(f"OBB: {obb.xywhr[0].tolist()}")
Training Custom Model
1. Dataset Preparation
Dataset must be in YOLO format. Folder structure:
dataset/
├── images/
│ ├── train/
│ │ ├── img001.jpg
│ │ ├── img002.jpg
│ │ └── ...
│ └── val/
│ ├── img001.jpg
│ └── ...
├── labels/
│ ├── train/
│ │ ├── img001.txt
│ │ ├── img002.txt
│ │ └── ...
│ └── val/
│ ├── img001.txt
│ └── ...
└── data.yaml
Label Format (YOLO format):
Each .txt file contains annotations:
classid xcenter ycenter width height
All coordinates are normalized (0-1). Example img001.txt:
0 0.5 0.5 0.3 0.4
1 0.2 0.3 0.1 0.2
data.yaml file:
# data.yaml
path: /path/to/dataset
train: images/train
val: images/val
Classes
names:
0: person
1: car
2: bicycle
3: motorcycle
Number of classes
nc: 4
2. Training
from ultralytics import YOLO
Load pretrained model as base
model = YOLO('yolov8n.pt')
Train
results = model.train(
data='data.yaml',
epochs=100,
imgsz=640,
batch=16,
name='mycustommodel',
patience=50, # Early stopping
save=True,
device=0, # GPU 0, or 'cpu'
)
Important Training Parameters:
model.train(
# Data
data='data.yaml',
# Training duration
epochs=100,
patience=50, # Early stopping patience
# Batch and image size
batch=16, # Batch size (-1 for AutoBatch)
imgsz=640, # Image size
# Optimization
optimizer='auto', # SGD, Adam, AdamW, etc.
lr0=0.01, # Initial learning rate
lrf=0.01, # Final learning rate (lr0 * lrf)
momentum=0.937,
weightdecay=0.0005,
# Augmentation
hsvh=0.015, # Hue augmentation
hsvs=0.7, # Saturation augmentation
hsvv=0.4, # Value augmentation
degrees=0.0, # Rotation
translate=0.1,
scale=0.5,
fliplr=0.5, # Horizontal flip probability
mosaic=1.0, # Mosaic augmentation
mixup=0.0, # Mixup augmentation
# Hardware
device=0, # GPU device
workers=8, # Dataloader workers
# Saving
project='runs/train',
name='exp',
save=True,
saveperiod=-1, # Save checkpoint every x epochs
# Resume training
resume=False,
# Pretrained
pretrained=True,
# Validation
val=True,
plots=True,
)
3. Monitor Training
Training progress can be monitored with TensorBoard:
tensorboard --logdir runs/train
Or view results in runs/train/exp/ folder:
results.csv- Metrics per epochresults.png- Training curvesconfusionmatrix.png- Confusion matrixweights/best.pt- Best model weightsweights/last.pt- Last epoch weights
4. Model Validation
from ultralytics import YOLO
Load trained model
model = YOLO('runs/train/exp/weights/best.pt')
Validate
metrics = model.val(data='data.yaml')
print(f"mAP50: {metrics.box.map50:.4f}")
print(f"mAP50-95: {metrics.box.map:.4f}")
print(f"Precision: {metrics.box.mp:.4f}")
print(f"Recall: {metrics.box.mr:.4f}")
Fine-tuning and Transfer Learning
1. Fine-tune on Small Dataset
from ultralytics import YOLO
Start from pretrained COCO model
model = YOLO('yolov8n.pt')
Fine-tune with small learning rate
results = model.train(
data='customdata.yaml',
epochs=50,
imgsz=640,
batch=16,
lr0=0.001, # Smaller learning rate
freeze=10, # Freeze first 10 layers
)
2. Transfer Learning from Custom Model
from ultralytics import YOLO
Load custom trained model
model = YOLO('path/to/custommodel.pt')
Continue training on new dataset
results = model.train(
data='newdataset.yaml',
epochs=30,
lr0=0.0001, # Very small LR
)
Export Model
1. Export to Various Formats
from ultralytics import YOLO
model = YOLO('yolov8n.pt')
Export to ONNX
model.export(format='onnx', dynamic=True, simplify=True)
Export to TensorRT (for NVIDIA)
model.export(format='engine', device=0, half=True)
Export to CoreML (for Apple)
model.export(format='coreml')
Export to TFLite (for mobile)
model.export(format='tflite')
Export to OpenVINO (for Intel)
model.export(format='openvino')
Supported Formats:
| Format | Argument | Use Case |
|--------|----------|----------|
| PyTorch | - | Training, development |
| ONNX | onnx | Cross-platform |
| TensorRT | engine | NVIDIA GPU inference |
| CoreML | coreml | iOS/macOS |
| TFLite | tflite | Android, Edge |
| OpenVINO | openvino | Intel hardware |
| NCNN | ncnn | Mobile |
| PaddlePaddle | paddle | Baidu ecosystem |
2. Inference with Exported Model
from ultralytics import YOLO
Load ONNX model
model = YOLO('yolov8n.onnx')
Inference as usual
results = model('image.jpg')
Performance Optimization
1. Batch Inference
from ultralytics import YOLO
model = YOLO('yolov8n.pt')
Batch inference for higher throughput
images = ['img1.jpg', 'img2.jpg', 'img3.jpg', 'img4.jpg']
results = model(images, batch=4)
2. Half Precision (FP16)
from ultralytics import YOLO
model = YOLO('yolov8n.pt')
Inference with FP16
results = model('image.jpg', half=True)
3. Object Tracking
from ultralytics import YOLO
model = YOLO('yolov8n.pt')
Video with tracking
results = model.track(
source='video.mp4',
tracker='bytetrack.yaml', # or 'botsort.yaml'
persist=True, # Persist tracks across frames
stream=True
)
for result in results:
boxes = result.boxes
if boxes.id is not None:
trackids = boxes.id.int().cpu().tolist()
for box, trackid in zip(boxes, trackids):
print(f"Track ID: {trackid}, Class: {model.names[int(box.cls)]}")
Complete Application Examples
1. Object Counting System
from ultralytics import YOLO
import cv2
from collections import defaultdict
model = YOLO('yolov8n.pt')
Track history for each object
trackhistory = defaultdict(lambda: [])
objectcounts = defaultdict(int)
cap = cv2.VideoCapture('traffic.mp4')
Define counting line
liney = 300
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# Run tracking
results = model.track(frame, persist=True, verbose=False)
if results[0].boxes.id is not None:
boxes = results[0].boxes.xyxy.cpu().numpy()
trackids = results[0].boxes.id.int().cpu().tolist()
classes = results[0].boxes.cls.int().cpu().tolist()
for box, trackid, cls in zip(boxes, trackids, classes):
x1, y1, x2, y2 = box
centery = (y1 + y2) / 2
# Store track history
track = trackhistory[trackid]
track.append(centery)
# Check if crossed the line
if len(track) > 1:
if track[-2] < liney <= track[-1]:
classname = model.names[cls]
objectcounts[classname] += 1
print(f"Counted: {classname} (Total: {objectcounts[classname]})")
# Draw counting line
cv2.line(frame, (0, liney), (frame.shape[1], liney), (0, 255, 0), 2)
# Draw counts
yoffset = 30
for clsname, count in objectcounts.items():
cv2.putText(frame, f'{clsname}: {count}', (10, yoffset),
cv2.FONTHERSHEYSIMPLEX, 0.7, (0, 255, 0), 2)
yoffset += 25
# Display
annotatedframe = results[0].plot()
cv2.imshow('Counting', annotatedframe)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
print("\nFinal counts:")
for clsname, count in objectcounts.items():
print(f" {clsname}: {count}")
2. REST API with FastAPI
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import JSONResponse
from ultralytics import YOLO
import cv2
import numpy as np
from io import BytesIO
from PIL import Image
app = FastAPI()
model = YOLO('yolov8n.pt')
@app.post("/detect")
async def detectobjects(file: UploadFile = File(...)):
# Read image
contents = await file.read()
image = Image.open(BytesIO(contents))
imagenp = np.array(image)
# Run inference
results = model(imagenp)
# Format response
detections = []
for box in results[0].boxes:
detections.append({
"class": model.names[int(box.cls)],
"confidence": float(box.conf),
"bbox": box.xyxy[0].tolist()
})
return JSONResponse(content={
"success": True,
"detections": detections,
"count": len(detections)
})
@app.get("/health")
async def healthcheck():
return {"status": "healthy", "model": "yolov8n"}
Run: uvicorn main:app --host 0.0.0.0 --port 8000
Tips and Best Practices
1. Choosing the Right Model
- Edge devices (Raspberry Pi, Jetson Nano): yolov8n or yolov8s
- Desktop/Server with GPU: yolov8m or yolov8l
- Maximum accuracy: yolov8x
- Real-time video: yolov8n with TensorRT
2. Improving Accuracy
# Use Test Time Augmentation (TTA)
results = model('image.jpg', augment=True)
Increase input resolution
results = model('image.jpg', imgsz=1280)
Lower confidence threshold for higher recall
results = model('image.jpg', conf=0.1)
3. Debugging
# Verbose output
results = model('image.jpg', verbose=True)
Save results
results = model('image.jpg', save=True, savetxt=True)
Visualize
results[0].show() # Display
results[0].save('output.jpg') # Save
4. Memory Management
import torch
Clear GPU cache
torch.cuda.emptycache()
Limit GPU memory
torch.cuda.setperprocessmemoryfraction(0.5) # Use max 50% GPU memory
Conclusion
Ultralytics provides an easy-to-use framework for object detection and other computer vision tasks. Key takeaways:
With Ultralytics, you can quickly build computer vision applications from prototype to production.