【零基础入门】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 标注步骤
  1. 打开图片文件夹:点击"Open Dir"选择包含待标注图片的文件夹
  2. 设置保存路径:点击"Change Save Dir"选择标注文件保存位置
  3. 选择YOLO格式:点击"YOLO"按钮(确保是YOLO格式)
  4. 开始标注
    • w键开始画框
    • 拖动鼠标框选目标
    • 输入类别名称(如果是首次标注,需要输入并创建)
  5. 保存:按Ctrl+S保存当前图片的标注
  6. 下一张:按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 实现步骤

  1. 数据收集:使用NEU或GC10-DET数据集,或自己用手机拍摄
  2. 数据标注:用LabelImg标注缺陷区域
  3. 数据划分:80%训练,20%验证
  4. 模型训练:训练YOLOv8模型
  5. 模型评估:验证集上mAP50达到0.9以上
  6. 模型推理:编写推理脚本,可视化结果

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应用中,实现工业缺陷检测原型系统,包括运动控制模拟、相机模拟和实时检测界面。


📚 参考文档链接


如果在学习过程中遇到任何问题,欢迎随时交流!下一阶段我们将进入激动人心的综合项目实战。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐