各版本模型加载与推理
Ultralytics 统一 API(v8/11/26 通用)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| from ultralytics import YOLO
# ========== YOLOv8 ==========
model_v8 = YOLO("yolov8n.pt") # nano
model_v8 = YOLO("yolov8s.pt") # small
model_v8 = YOLO("yolov8m.pt") # medium
model_v8 = YOLO("yolov8l.pt") # large
model_v8 = YOLO("yolov8x.pt") # extra large
# ========== YOLO11 ==========
model_11 = YOLO("yolo11n.pt") # nano
model_11 = YOLO("yolo11s.pt") # small
model_11 = YOLO("yolo11m.pt") # medium
model_11 = YOLO("yolo11l.pt") # large
model_11 = YOLO("yolo11x.pt") # extra large
# ========== YOLO26 (2026最新) ==========
model_26 = YOLO("yolo26n.pt") # nano 推荐边缘部署
model_26 = YOLO("yolo26s.pt") # small
model_26 = YOLO("yolo26m.pt") # medium
model_26 = YOLO("yolo26l.pt") # large
model_26 = YOLO("yolo26x.pt") # extra large
|
图片检测实战
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| from ultralytics import YOLO
# 加载模型(以YOLO26为例)
model = YOLO("yolo26n.pt")
# 单张图片检测
results = model("test.jpg", conf=0.25, iou=0.45)
# 结果处理
for result in results:
boxes = result.boxes # 检测框
masks = result.masks # 分割掩码
probs = result.probs # 分类概率
# 打印检测结果
for box in boxes:
print(f"类别: {result.names[int(box.cls)]}, "
f"置信度: {box.conf.item():.3f}, "
f"坐标: {box.xyxy.tolist()[0]}")
# 保存可视化结果
result.save("result.jpg")
|
视频检测实战
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| from ultralytics import YOLO
model = YOLO("yolo26n.pt")
# 视频文件检测
results = model.predict(
source="input.mp4",
save=True, # 保存结果视频
conf=0.3,
show=False, # 是否实时显示
stream=True # 流式处理,节省内存
)
# 逐帧处理
for result in results:
# 自定义后处理逻辑
pass
|
摄像头实时检测
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| from ultralytics import YOLO
import cv2
model = YOLO("yolo26n.pt")
# 打开摄像头
cap = cv2.VideoCapture(0) # 0为默认摄像头
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 推理
results = model(frame, verbose=False)
# 绘制结果
annotated_frame = results[0].plot()
# 显示
cv2.imshow("YOLO Real-time", annotated_frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
|
各版本代码差异说明
| 特性 | YOLOv8 | YOLO11 | YOLO26 | YOLOv9 | YOLOv10 |
|---|
| API 统一 | ✅ | ✅ | ✅ | ❌ 独立仓库 | ❌ 独立仓库 |
| 无 NMS | ❌ | ❌ | ✅ | ❌ | ✅ |
| DFL 模块 | ✅ | ✅ | ❌ 已移除 | ✅ | ✅ |
| MuSGD 优化器 | ❌ | ❌ | ✅ | ❌ | ❌ |
| 导出兼容性 | 良好 | 良好 | 最佳 | 一般 | 一般 |
Results 对象 API 详解
model() 或 model.predict() 返回的是一个 Results 对象列表。每个 Results 对象封装了单张图片的所有推理输出。理解其内部结构是进行后续处理的基础。
核心属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| from ultralytics import YOLO
model = YOLO("yolo26n.pt")
results = model("test.jpg")[0] # 取第一张图的结果
# === 检测框 (Boxes) ===
boxes = results.boxes
# Boxes 对象属性:
print(boxes.xyxy) # Tensor[N,4] — 左上右下坐标 (x1,y1,x2,y2)
print(boxes.xywh) # Tensor[N,4] — 中心宽高格式 (cx,cy,w,h)
print(boxes.xyxyn) # Tensor[N,4] — 归一化 xyxy (0~1)
print(boxes.xywhn) # Tensor[N,4] — 归一化 xywh (0~1)
print(boxes.conf) # Tensor[N] — 每个框的置信度
print(boxes.cls) # Tensor[N] — 每个框的类别索引
print(boxes.id) # Tensor[N] — 跟踪 ID(仅跟踪场景)
# === 分割掩码 (Masks) ===
masks = results.masks
if masks is not None:
print(masks.data) # Tensor[N,H,W] — 原始掩码张量
print(masks.xy) # list[N] of numpy arrays — 多边形轮廓点
# === 分类概率 (Probs) ===
# 仅分类模型(非检测模型)有该属性
probs = results.probs
if probs is not None:
print(probs.top1) # 最高概率类别索引
print(probs.top1conf) # 最高概率置信度
print(probs.top5) # Top-5 类别索引 (list)
# === 关键点 (Keypoints) ===
# 姿态估计模型(如 YOLO11-pose)
keypoints = results.keypoints
if keypoints is not None:
print(keypoints.data) # Tensor[N,17,3] — (x, y, confidence)
print(keypoints.xy) # Tensor[N,17,2] — 仅坐标
print(keypoints.conf) # Tensor[N,17] — 关键点置信度
# === 原始图像 ===
print(results.orig_img.shape) # (H, W, C) — 原始图像 numpy 数组
print(results.orig_shape) # (H, W) — 原始尺寸
# === 类别名称映射 ===
print(results.names) # {0: 'person', 1: 'bicycle', ...}
# === 推理速度 ===
print(results.speed) # {'preprocess': 1.2, 'inference': 8.5, 'postprocess': 0.8}
|
按条件过滤检测框
1
2
3
4
5
6
7
| # 只保留置信度 > 0.5 且类别为 person (0) 的检测框
results = model("test.jpg")[0]
person_boxes = [
box for box in results.boxes
if box.conf.item() > 0.5 and int(box.cls) == 0
]
print(f"检测到 {len(person_boxes)} 个行人")
|
后处理参数详解
model() 和 model.predict() 的核心参数控制着推理结果的质量和数量。
置信度阈值 (conf)
1
2
| # conf=0.25 表示只保留置信度 ≥ 0.25 的检测框
results = model("test.jpg", conf=0.25)
|
- 默认值: 0.25
- 调高(如 0.5): 减少误检,适合精确度要求高的场景(工业生产)
- 调低(如 0.1): 增加召回率,适合需要不漏检的场景(安防监控)
置信度是模型对每个检测框的"自信程度",由分类分支的输出经 Sigmoid 归一化到 0~1。
IoU 阈值与 NMS
1
2
| # iou=0.45 控制 NMS 的严格程度
results = model("test.jpg", iou=0.45)
|
NMS (Non-Maximum Suppression, 非极大值抑制) 是目标检测的后处理核心技术:
- 按置信度对所有检测框排序
- 选中置信度最高的框
- 删除与其 IoU > 阈值的其他框(视为重复检测)
- 重复步骤 2-3,直到没有剩余框
- IoU 调高(如 0.7): 保留更多重叠框,适合密集场景
- IoU 调低(如 0.3): 删除更多重叠框,减少冗余
YOLO26 的特殊性: YOLO26 采用 SimOTA 标签分配策略,推理时不需要 NMS。这意味着无论 iou 参数怎么设置,YOLO26 都不会执行 NMS 步骤——这是其架构设计的关键差异,也是速度优势的来源之一。
其他后处理参数
1
2
3
4
5
6
7
8
| results = model.predict(
source="test.jpg",
conf=0.25, # 置信度阈值
iou=0.45, # NMS IoU 阈值
max_det=300, # 每张图最大检测框数(默认 300)
agnostic_nms=False, # 是否按类别独立 NMS
half=False, # 是否使用 FP16
)
|
批量推理
处理大量图片时,批量推理能充分利用 GPU 并行计算能力。
多图片同时推理
1
2
3
4
5
6
7
8
9
10
| from ultralytics import YOLO
model = YOLO("yolo26n.pt")
# 传入图片路径列表 — 自动 batch 推理
results = model(["img1.jpg", "img2.jpg", "img3.jpg"], batch=4)
for i, result in enumerate(results):
print(f"图片 {i+1}: 检测到 {len(result.boxes)} 个目标")
result.save(f"result_{i}.jpg")
|
batch 参数控制每次送入 GPU 的图片数量。默认值为 -1(自动选择),实际值受显存限制。
stream=True 内存优化
当图片数量极大(数百上千张)时,stream=True 是防止内存溢出的关键:
1
2
3
4
5
6
7
8
9
10
| # 普通模式 — 等待所有图片处理完成才返回
results = model(["img1.jpg", "img2.jpg", "img3.jpg"])
# 此时所有结果都在内存中
# 流式模式 — 处理完一张立即返回一张
results = model(["img1.jpg", "img2.jpg", "img3.jpg"], stream=True)
# results 是一个生成器 (generator),按需产生结果
for result in results:
# 处理完当前图片后,其内存可被回收
process(result)
|
stream=True 的工作原理:
model.predict(stream=True) 返回生成器而非列表- 生成器每次
yield 一个 Results 对象 - 单个结果处理完毕后,Python 可回收其内存
- 适合视频帧序列、大型数据集等场景
可视化自定义
result.plot() 方法提供了丰富的参数来控制可视化输出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| from ultralytics import YOLO
import cv2
model = YOLO("yolo26n.pt")
results = model("test.jpg")
for result in results:
# 自定义可视化
annotated = result.plot(
line_width=2, # 框线宽度(默认 3)
font_size=1.0, # 文字大小倍数(默认 1.0)
conf=True, # 是否在框上显示置信度(默认 True)
labels=True, # 是否显示类别标签(默认 True)
boxes=True, # 是否绘制检测框(默认 True)
masks=True, # 是否绘制分割掩码(默认 True)
probs=True, # 是否显示分类概率(默认 True)
)
# 保存自定义可视化结果
cv2.imwrite("custom_result.jpg", annotated)
|
参数详解
| 参数 | 类型 | 默认 | 说明 |
|---|
line_width | int | 3 | 检测框线宽,调大适合高清大图 |
font_size | float | 1.0 | 标签文字相对大小 |
conf | bool | True | 框上显示置信度数值 |
labels | bool | True | 显示类别名称 |
boxes | bool | True | 绘制边界框矩形 |
masks | bool | True | 绘制分割掩码(仅分割模型) |
probs | bool | True | 显示概率(仅分类模型) |
关闭所有标注,只保留原始图片
1
2
3
4
5
| result_clean = result.plot(
conf=False, labels=False, boxes=False,
masks=False, probs=False
)
# 等价于仅返回原始图像
|
不同格式保存结果
保存检测目标裁剪
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| from ultralytics import YOLO
import cv2
import os
model = YOLO("yolo26n.pt")
results = model("test.jpg")
for i, result in enumerate(results):
boxes = result.boxes
orig_img = result.orig_img # numpy array (H, W, 3)
os.makedirs("crops", exist_ok=True)
for j, box in enumerate(boxes):
# 获取框坐标 (整数)
x1, y1, x2, y2 = map(int, box.xyxy[0].tolist())
# 裁剪目标区域
crop = orig_img[y1:y2, x1:x2]
# 保存裁剪图
cls_name = result.names[int(box.cls[0])]
cv2.imwrite(f"crops/{cls_name}_{j}.jpg", crop)
|
导出 JSON / CSV
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| import json
import csv
results = model("test.jpg")
# === JSON 导出 ===
data = []
for result in results:
for box in result.boxes:
data.append({
"class": result.names[int(box.cls[0])],
"confidence": round(box.conf[0].item(), 3),
"bbox": {
"x1": round(box.xyxy[0][0].item(), 2),
"y1": round(box.xyxy[0][1].item(), 2),
"x2": round(box.xyxy[0][2].item(), 2),
"y2": round(box.xyxy[0][3].item(), 2),
},
"image_width": result.orig_shape[1],
"image_height": result.orig_shape[0],
})
with open("detections.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
# === CSV 导出 ===
with open("detections.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["class", "confidence", "x1", "y1", "x2", "y2"])
for result in results:
for box in result.boxes:
writer.writerow([
result.names[int(box.cls[0])],
round(box.conf[0].item(), 3),
*[round(v.item(), 2) for v in box.xyxy[0]],
])
|
推理性能优化技巧
半精度推理 (FP16)
半精度浮点数推理可将显存占用减半,在兼容硬件(NVIDIA Volta/Turing/Ampere 架构及以上)上显著加速:
1
2
3
4
5
6
7
8
| model = YOLO("yolo26n.pt")
# 方式一:predict 时指定
results = model.predict("test.jpg", half=True)
# 方式二:先转换模型
model.model.half() # 全局启用 FP16
results = model("test.jpg")
|
注意: FP16 在某些 CPU 和旧 GPU(如 GTX 10 系列)上不支持,会回退到 FP32。
设备选择
1
2
3
4
5
6
7
8
9
10
| # 指定 GPU 设备
model = YOLO("yolo26n.pt").to("cuda:0") # 第一块 GPU
model = YOLO("yolo26n.pt").to("cuda:1") # 第二块 GPU
# 多 GPU 推理(需较大 batch)
model = YOLO("yolo26n.pt")
results = model.predict(["img1.jpg", "img2.jpg"], device="0,1") # 使用 GPU 0 和 1
# CPU 推理(显存不足时)
model = YOLO("yolo26n.pt").to("cpu")
|
预热推理 (Warm-up)
深度模型首次推理时包含 CUDA 内核编译、内存分配等初始化开销。预热可以消除冷启动延迟:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| import time
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
# 预热:用一张空白图跑一次推理
import numpy as np
dummy = np.zeros((640, 640, 3), dtype=np.uint8)
_ = model(dummy, verbose=False) # 触发 CUDA 内核编译
# 正式计时
start = time.perf_counter()
results = model("test.jpg", verbose=False)
print(f"推理耗时: {(time.perf_counter() - start)*1000:.1f}ms")
|
Batch Size 调优
1
2
3
4
5
6
7
8
| # 批量推理自动选择最佳 batch size
# batch=-1 表示自动检测,也可以手动指定
results = model.predict(
source=["img1.jpg", "img2.jpg", "img3.jpg", "img4.jpg"],
batch=2, # 手动指定 batch size
half=True, # 配合 FP16 降低显存
device="cuda:0",
)
|
Batch Size 经验值:
| 模型 | FP32 batch=1 | FP16 batch=1 | FP32 batch=4 | FP16 batch=4 |
|---|
| YOLO26n | ~1.2 GB | ~0.7 GB | ~1.8 GB | ~1.0 GB |
| YOLO26s | ~2.0 GB | ~1.1 GB | ~3.2 GB | ~1.7 GB |
| YOLO26m | ~3.5 GB | ~1.9 GB | ~6.0 GB | ~3.2 GB |
以上为 640×640 输入估算值,实际内存占用会因图片尺寸和检测框数量波动。
其他优化技巧
1
2
3
4
5
6
7
8
9
10
| model.predict(
source="input.mp4",
stream=True, # 流式处理防内存溢出
half=True, # FP16 加速
device="cuda:0", # 显式指定设备
verbose=False, # 关闭日志输出,减少 IO
max_det=100, # 限制最大检测框数
iou=0.5, # 较高 IoU 阈值减少 NMS 保留框数
conf=0.3, # 较高置信度阈值减少后处理量
)
|
这些参数组合可以针对你的具体场景找到推理速度与精度的最佳平衡点。