【零基础入门】Python机器视觉第五阶段:目标检测实战(YOLOv8)
本文介绍了Python机器视觉中目标检测的实战应用,重点讲解了YOLOv8框架的使用。主要内容包括: 学习目标:掌握目标检测核心概念(边界框、IOU、mAP等)、YOLOv8的安装与使用、数据集标注与训练方法。 目标检测基础:解释了边界框、IOU等核心概念,并介绍了YOLO系列算法的特点,特别是YOLOv8的Anchor-Free架构和多任务支持优势。 实战操作指南: 提供YOLOv8安装命令 演
【零基础入门】Python机器视觉第五阶段:目标检测实战(YOLOv8)
。在第四阶段,我们学习了PyTorch基础并搭建了CNN网络进行图像分类。从分类到检测,是机器视觉能力的一次重要跃升——分类回答“这是什么”,检测回答“它在哪里”。本阶段我们将学习目前最流行的目标检测框架YOLOv8,并实战训练一个能够检测表面缺陷(如划痕、脏污、裂纹)的模型。
本文所有代码均可直接复制运行,建议结合官方文档和数据集边学边练。
一、本阶段学习目标
- 理解目标检测的基本概念:边界框、IOU、mAP、NMS
- 掌握YOLOv8的安装与使用
- 学会使用LabelImg标注自己的数据集
- 掌握YOLO格式数据集的制作与划分
- 能够训练YOLOv8模型进行缺陷检测
- 学会模型推理与结果可视化
- 掌握模型评估指标的含义与使用方法
二、目标检测核心概念速览
2.1 什么是目标检测?
目标检测的任务是:在图像中找出所有感兴趣的目标,并给出它们的类别和位置。位置通常用**边界框(Bounding Box)**表示。
2.2 核心概念
| 概念 | 通俗解释 | 图示/公式 |
|---|---|---|
| 边界框 | 包含目标的最小矩形,用(x1,y1,x2,y2)或(x_center,y_center,width,height)表示 |
矩形框 |
| IOU(交并比) | 预测框与真实框的重叠程度,值越大表示预测越准 | IOU = 交集面积 / 并集面积 |
| 置信度 | 模型对预测结果的信心,取值范围0~1 | - |
| NMS(非极大值抑制) | 去除冗余的重复检测框,保留最优的一个 | 算法 |
| mAP(平均精度均值) | 目标检测最常用的评估指标 | 综合所有类别的AP取平均 |
2.3 YOLO系列简介
YOLO(You Only Look Once)是一种单阶段目标检测算法,特点是速度快、精度高。YOLOv8是Ultralytics公司发布的最新版本,支持:
- 目标检测(Object Detection)
- 实例分割(Instance Segmentation)
- 图像分类(Image Classification)
- 姿态估计(Pose Estimation)
YOLOv8的优势:
- Anchor-Free架构,简化设计
- 支持多种模型大小(n/s/m/l/x)以适应不同场景
- 提供完整的训练、验证、预测、导出工具链
- 与PyTorch无缝集成
三、YOLOv8基础
3.1 安装YOLOv8
# 安装ultralytics包
pip install ultralytics
# 验证安装
python -c "from ultralytics import YOLO; print(YOLO.__version__)"
3.2 使用预训练模型进行推理
from ultralytics import YOLO
import cv2
import matplotlib.pyplot as plt
# 加载预训练模型(自动下载)
model = YOLO('yolov8n.pt') # n: nano, s: small, m: medium, l: large, x: xlarge
# 对图片进行推理
results = model('test.jpg') # 替换为你的图片路径
# 显示结果
img = cv2.imread('test.jpg')
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
for r in results:
boxes = r.boxes
for box in boxes:
x1, y1, x2, y2 = box.xyxy[0].tolist()
conf = box.conf[0].item()
cls = int(box.cls[0].item())
label = f"{model.names[cls]} {conf:.2f}"
# 画框
cv2.rectangle(img_rgb, (int(x1), int(y1)), (int(x2), int(y2)), (255,0,0), 2)
cv2.putText(img_rgb, label, (int(x1), int(y1)-5),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,0,0), 2)
plt.imshow(img_rgb)
plt.axis('off')
plt.show()
3.3 YOLOv8支持的模型版本
| 模型 | 参数量 | mAP50-95 | 速度(CPU) | 适用场景 |
|---|---|---|---|---|
| YOLOv8n | 3.2M | 37.3 | 最快 | 移动端、边缘设备 |
| YOLOv8s | 11.2M | 44.9 | 较快 | 通用场景 |
| YOLOv8m | 25.9M | 50.2 | 中等 | 平衡速度和精度 |
| YOLOv8l | 43.7M | 52.9 | 较慢 | 高精度要求 |
| YOLOv8x | 68.2M | 53.9 | 最慢 | 极致精度 |
四、数据集准备
4.1 YOLO数据集格式
YOLO使用特定的数据集格式:
dataset/
├── images/
│ ├── train/ # 训练图片
│ └── val/ # 验证图片
├── labels/
│ ├── train/ # 训练标注
│ └── val/ # 验证标注
└── data.yaml # 数据集配置文件
标注文件格式:每张图片对应一个同名的txt文件,每行代表一个目标:
class_id x_center y_center width height
class_id:类别ID(从0开始)x_center, y_center:边界框中心点坐标(归一化到0-1)width, height:边界框的宽和高(归一化到0-1)
例如:
0 0.5096 0.3528 0.3947 0.3182 # 划痕
1 0.1234 0.5678 0.2345 0.3456 # 脏污
4.2 使用LabelImg标注工具
4.2.1 安装LabelImg
pip install labelImg
4.2.2 启动标注工具
labelImg
4.2.3 标注步骤
- 打开图片文件夹:点击"Open Dir"选择包含待标注图片的文件夹
- 设置保存路径:点击"Change Save Dir"选择标注文件保存位置
- 选择YOLO格式:点击"YOLO"按钮(确保是YOLO格式)
- 开始标注:
- 按
w键开始画框 - 拖动鼠标框选目标
- 输入类别名称(如果是首次标注,需要输入并创建)
- 按
- 保存:按
Ctrl+S保存当前图片的标注 - 下一张:按
d键进入下一张图片
4.3 数据集配置文件 data.yaml
# 数据集根路径(建议使用绝对路径)
path: D:/defect_dataset # 修改为你的实际路径
train: images/train # 训练图片路径(相对于path)
val: images/val # 验证图片路径(相对于path)
# 类别数量
nc: 4
# 类别名称
names:
0: scratch # 划痕
1: dirt # 脏污
2: dimple # 凹坑
3: crack # 裂纹
4.4 数据集划分脚本
import os
import random
import shutil
from sklearn.model_selection import train_test_split
def split_dataset(image_dir, label_dir, output_dir, val_ratio=0.2, random_seed=42):
"""
将数据集划分为训练集和验证集
Args:
image_dir: 原始图片目录
label_dir: 原始标注目录
output_dir: 输出目录
val_ratio: 验证集比例
random_seed: 随机种子
"""
# 创建目录结构
train_img_dir = os.path.join(output_dir, 'images', 'train')
train_label_dir = os.path.join(output_dir, 'labels', 'train')
val_img_dir = os.path.join(output_dir, 'images', 'val')
val_label_dir = os.path.join(output_dir, 'labels', 'val')
for d in [train_img_dir, train_label_dir, val_img_dir, val_label_dir]:
os.makedirs(d, exist_ok=True)
# 获取所有图片文件
images = [f for f in os.listdir(image_dir)
if f.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp'))]
# 划分训练集和验证集
train_images, val_images = train_test_split(
images, test_size=val_ratio, random_state=random_seed
)
# 复制文件
for img in train_images:
# 复制图片
src_img = os.path.join(image_dir, img)
dst_img = os.path.join(train_img_dir, img)
shutil.copy(src_img, dst_img)
# 复制对应的标注文件
label_file = os.path.splitext(img)[0] + '.txt'
src_label = os.path.join(label_dir, label_file)
if os.path.exists(src_label):
dst_label = os.path.join(train_label_dir, label_file)
shutil.copy(src_label, dst_label)
for img in val_images:
# 复制图片
src_img = os.path.join(image_dir, img)
dst_img = os.path.join(val_img_dir, img)
shutil.copy(src_img, dst_img)
# 复制对应的标注文件
label_file = os.path.splitext(img)[0] + '.txt'
src_label = os.path.join(label_dir, label_file)
if os.path.exists(src_label):
dst_label = os.path.join(val_label_dir, label_file)
shutil.copy(src_label, dst_label)
print(f"数据集划分完成!")
print(f"训练集: {len(train_images)} 张图片")
print(f"验证集: {len(val_images)} 张图片")
# 使用示例
split_dataset(
image_dir='./raw_images',
label_dir='./raw_labels',
output_dir='./defect_dataset',
val_ratio=0.2
)
4.5 下载公开缺陷数据集(推荐)
4.5.1 NEU表面缺陷数据集
钢铁表面缺陷数据集,包含6类缺陷:划痕、氧化皮、裂纹等。
# 安装kagglehub
pip install kagglehub
import kagglehub
# 下载NEU数据集
path = kagglehub.dataset_download("kaustubhdhake/neu-surface-defect-database")
print("数据集下载到:", path)
4.5.2 GC10-DET数据集
金属表面缺陷数据集,包含10类缺陷。
path = kagglehub.dataset_download("shadabhussain/gc10det")
print("数据集下载到:", path)
4.5.3 PCB缺陷数据集
电路板缺陷数据集,包含6类缺陷。
path = kagglehub.dataset_download("akhatova/pcb-defects")
print("数据集下载到:", path)
五、训练YOLOv8模型
5.1 训练脚本
from ultralytics import YOLO
import torch
# ---------- 1. 检查GPU ----------
print(f"CUDA可用: {torch.cuda.is_available()}")
if torch.cuda.is_available():
print(f"GPU型号: {torch.cuda.get_device_name(0)}")
# ---------- 2. 加载预训练模型 ----------
# 可选:yolov8n.pt, yolov8s.pt, yolov8m.pt, yolov8l.pt, yolov8x.pt
model = YOLO('yolov8n.pt')
# ---------- 3. 开始训练 ----------
results = model.train(
data='defect_dataset/data.yaml', # 数据集配置文件
epochs=100, # 训练轮数
imgsz=640, # 输入图片大小
batch=16, # 批次大小(根据显存调整)
workers=4, # 数据加载线程数
device='0', # GPU设备('0'表示第一个GPU,'cpu'表示CPU)
lr0=0.001, # 初始学习率
optimizer='SGD', # 优化器
patience=20, # 早停耐心值(20轮无改善则停止)
save=True, # 保存模型
project='runs/train', # 项目保存路径
name='defect_detection', # 实验名称
exist_ok=True, # 覆盖已有实验
pretrained=True, # 使用预训练权重
verbose=True # 打印详细信息
)
print("训练完成!")
5.2 训练参数详解
| 参数 | 说明 | 推荐值 | 经验建议 |
|---|---|---|---|
epochs |
训练轮数 | 100-300 | 小数据集100足够,大数据集可增加 |
imgsz |
输入图片大小 | 640 | 越大越慢但可能更准 |
batch |
批次大小 | 8-32 | 根据显存调整,越大训练越稳定 |
lr0 |
初始学习率 | 0.001 | 太大不收敛,太小收敛慢 |
patience |
早停耐心值 | 20-50 | 防止过拟合 |
workers |
数据加载线程 | 4-8 | 根据CPU核心数调整 |
5.3 训练过程监控
训练过程中,YOLOv8会实时显示:
- Epoch:当前训练轮数
- GPU_mem:GPU内存占用
- box_loss:边界框损失
- cls_loss:分类损失
- dfl_loss:分布焦点损失
- mAP50:IoU=0.5时的平均精度
- mAP50-95:IoU从0.5到0.95的平均精度
5.4 训练结果
训练完成后,在 runs/train/defect_detection/ 目录下生成:
weights/
├── best.pt # 最佳模型(根据验证集mAP)
└── last.pt # 最后一轮模型
results.png # 训练曲线
confusion_matrix.png # 混淆矩阵
F1_curve.png # F1曲线
PR_curve.png # PR曲线
labels.jpg # 标注示例
5.5 模型验证
from ultralytics import YOLO
# 加载训练好的模型
model = YOLO('runs/train/defect_detection/weights/best.pt')
# 在验证集上评估
metrics = model.val(data='defect_dataset/data.yaml')
print(f"mAP50: {metrics.box.map50:.4f}")
print(f"mAP50-95: {metrics.box.map:.4f}")
# 查看每个类别的AP
for i, class_name in enumerate(metrics.names.values()):
ap = metrics.box.ap[i] if hasattr(metrics.box, 'ap') else 0
print(f"{class_name}: mAP50 = {metrics.box.ap50[i]:.4f}")
六、模型推理与可视化
6.1 单张图片推理
from ultralytics import YOLO
import cv2
import matplotlib.pyplot as plt
# 加载模型
model = YOLO('runs/train/defect_detection/weights/best.pt')
# 推理
results = model('test.jpg', conf=0.25, save=True) # conf=置信度阈值
# 自定义可视化
img = cv2.imread('test.jpg')
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
for r in results:
boxes = r.boxes
for box in boxes:
x1, y1, x2, y2 = box.xyxy[0].tolist()
conf = box.conf[0].item()
cls = int(box.cls[0].item())
label = f"{model.names[cls]} {conf:.2f}"
# 画框
cv2.rectangle(img_rgb, (int(x1), int(y1)), (int(x2), int(y2)), (255,0,0), 2)
cv2.putText(img_rgb, label, (int(x1), int(y1)-5),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,0,0), 2)
print(f"检测到: {label}, 位置: ({x1:.1f}, {y1:.1f}, {x2:.1f}, {y2:.1f})")
plt.figure(figsize=(10,8))
plt.imshow(img_rgb)
plt.axis('off')
plt.show()
6.2 批量推理
# 对整个文件夹进行推理
results = model.predict(
source='./test_images/', # 图片文件夹
conf=0.25, # 置信度阈值
save=True, # 保存结果
project='./predict_results', # 输出目录
name='defect_detection' # 实验名称
)
6.3 视频推理
# 对视频文件进行推理
results = model.predict(
source='test_video.mp4', # 视频文件
conf=0.25,
save=True,
project='./predict_results'
)
6.4 摄像头实时检测
import cv2
from ultralytics import YOLO
model = YOLO('runs/train/defect_detection/weights/best.pt')
cap = cv2.VideoCapture(0) # 0表示默认摄像头
while True:
ret, frame = cap.read()
if not ret:
break
# 推理
results = model(frame, conf=0.25)[0]
# 绘制结果
for box in results.boxes:
x1, y1, x2, y2 = map(int, box.xyxy[0])
conf = box.conf[0].item()
cls = int(box.cls[0].item())
label = f"{model.names[cls]} {conf:.2f}"
cv2.rectangle(frame, (x1, y1), (x2, y2), (0,255,0), 2)
cv2.putText(frame, label, (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 2)
cv2.imshow('YOLOv8 Detection', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
七、模型评估与优化
7.1 评估指标详解
| 指标 | 含义 | 优秀值 |
|---|---|---|
| mAP50 | IoU阈值0.5时的平均精度 | >0.9 |
| mAP50-95 | IoU从0.5到0.95的平均精度 | >0.5(小目标) |
| Precision | 预测为正例中实际为正例的比例 | >0.9 |
| Recall | 实际为正例中被正确预测的比例 | >0.9 |
| F1-score | 精确率和召回率的调和平均 | >0.9 |
7.2 常见问题与解决方案
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| mAP低 | 数据集太小 | 数据增强、使用预训练模型 |
| 标注不准确 | 重新检查标注 | |
| 类别不平衡 | 调整损失权重、过采样 | |
| 过拟合 | 训练轮数太多 | 早停、增加正则化 |
| 数据集太小 | 数据增强、迁移学习 | |
| 漏检 | 目标太小 | 使用更大输入尺寸 |
| 置信度阈值太高 | 降低conf阈值 | |
| 误检 | 背景干扰 | 增加负样本、调整NMS |
7.3 超参数调优建议
# 建议尝试不同的学习率和优化器
model.train(
lr0=0.01, # 较高的初始学习率
optimizer='AdamW', # 尝试不同优化器
augment=True, # 启用数据增强
mosaic=1.0, # Mosaic增强
mixup=0.5 # MixUp增强
)
八、实战项目:表面缺陷检测系统
8.1 项目目标
训练一个能够检测3-5类表面缺陷(如划痕、脏污、凹坑、裂纹)的YOLOv8模型。
8.2 实现步骤
- 数据收集:使用NEU或GC10-DET数据集,或自己用手机拍摄
- 数据标注:用LabelImg标注缺陷区域
- 数据划分:80%训练,20%验证
- 模型训练:训练YOLOv8模型
- 模型评估:验证集上mAP50达到0.9以上
- 模型推理:编写推理脚本,可视化结果
8.3 完整代码(训练+推理)
# train_defect_detector.py
from ultralytics import YOLO
def train_model():
# 加载模型
model = YOLO('yolov8n.pt')
# 训练
results = model.train(
data='defect_dataset/data.yaml',
epochs=100,
imgsz=640,
batch=16,
workers=4,
device='0',
lr0=0.001,
optimizer='SGD',
patience=20,
project='runs/train',
name='defect_detection'
)
# 验证
metrics = model.val()
print(f"mAP50: {metrics.box.map50:.4f}")
return model
def predict(model, image_path):
results = model(image_path, conf=0.25)
# 打印结果
for r in results:
boxes = r.boxes
print(f"检测到 {len(boxes)} 个缺陷")
for box in boxes:
cls = int(box.cls[0].item())
conf = box.conf[0].item()
print(f" {model.names[cls]}: {conf:.2f}")
if __name__ == '__main__':
model = train_model()
predict(model, 'test.jpg')
九、总结与下一步
通过本阶段的学习,你已经掌握了:
- ✅ 目标检测核心概念
- ✅ YOLOv8的安装与使用
- ✅ 使用LabelImg标注数据集
- ✅ 制作YOLO格式数据集
- ✅ 训练YOLOv8检测模型
- ✅ 模型推理与结果可视化
- ✅ 模型评估与优化技巧
下一步:进入第六阶段——综合项目实战,你将学习如何将训练好的YOLOv8模型集成到C# WPF应用中,实现工业缺陷检测原型系统,包括运动控制模拟、相机模拟和实时检测界面。
📚 参考文档链接
- Ultralytics YOLOv8官方文档 —— 完整的训练、预测、导出教程
- YOLOv8 Python API文档 —— 详细的API使用说明
- LabelImg GitHub —— 标注工具源码和使用说明
- NEU表面缺陷数据集 —— Kaggle上的钢铁表面缺陷数据集
- GC10-DET数据集 —— 金属表面缺陷数据集
- YOLOv8训练自己的数据集 —— CSDN中文教程
如果在学习过程中遇到任何问题,欢迎随时交流!下一阶段我们将进入激动人心的综合项目实战。
更多推荐
所有评论(0)