Files
YoloDemo/docs/1.YOLO模型测试流程指南.md
T
2026-05-05 01:07:49 +08:00

644 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# YOLO 模型测试流程指南
本文档基于知乎文章整理,帮助你从零开始完成一个 YOLO 目标检测项目的完整流程。
***
## 目录
1. [环境准备](#1-环境准备)
2. [数据收集与准备](#2-数据收集与准备)
3. [数据标注](#3-数据标注)
4. [数据格式转换](#4-数据格式转换)
5. [数据集划分](#5-数据集划分)
6. [模型训练](#6-模型训练)
7. [模型评估与测试](#7-模型评估与测试)
***
## 1. 环境准备
### 1.1 安装 Python 环境
确保 Python 版本 >= 3.8
```bash
python --version
```
### 1.2 创建虚拟环境
为了避免影响全局 Python 环境,建议为项目创建独立的虚拟环境。
**方式一:使用 conda**
**首先安装 Anaconda 或 Miniconda**
1. 下载 Miniconda(推荐,更轻量):<https://docs.conda.io/en/latest/miniconda.html>
2. 运行安装程序,勾选 "Add Miniconda to PATH"(或安装后手动配置)
3. 验证安装:
```bash
conda --version
```
**创建并激活虚拟环境:**
```bash
# 首次使用需要接受服务条款
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/msys2
//切换用清华的源
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
# 创建虚拟环境
conda create -n yolo_demo python=3.10 -y
# 激活虚拟环境
conda activate yolo_demo
conda env list
# 安装 pytorchGPU 支持,需要 CUDA
# 首先卸载 CPU 版本(如果已安装)
conda uninstall pytorch torchvision torchaudio -y
# 安装 PyTorch CUDA 版本(推荐 CUDA 12.1
conda install -v pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia -y
# pip 来安装 PyTorch 更稳定
conda activate yolo_demo ; pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
# 验证安装是否成功
python -c "import torch; print(f'PyTorch版本: {torch.__version__}'); print(f'CUDA可用: {torch.cuda.is_available()}')"
```
**查看已创建的环境:**
```bash
conda env list
```
**常见问题:**
如果遇到 `CondaToSNonInteractiveError` 错误,需要先运行上面的 `conda tos accept` 命令接受服务条款。
**验证虚拟环境已激活:**
激活后,终端提示符前会显示虚拟环境名称:
```bash
(yolo_demo) D:\Codes\AI\Yolo\YoloDemo>
```
**退出虚拟环境:**
```bash
# conda:
conda deactivate
```
### 1.3 安装 YOLOv8(推荐)
```bash
conda activate yolo_demo ;pip install ultralytics
```
### 1.4 验证安装
```bash
python -c "from ultralytics import YOLO; print('YOLOv8 安装成功')"
```
### 1.5 检查 GPU 支持(可选但推荐)
```bash
python -c "import torch; print(f'CUDA 可用: {torch.cuda.is_available()}')"
```
***
## 2. 数据收集与准备
### 2.1 确定检测目标
首先明确你要检测的类别,例如:
- car(汽车)
- person(行人)
- bicycle(自行车)
### 2.2 数据量建议
| 项目类型 | 每类最少图片 | 推荐图片数 |
| ---- | --------- | ------ |
| 快速原型 | 100-200 张 | 500 张 |
| 生产应用 | 1000 张 | 3000 张 |
### 2.3 数据来源
**方式一:使用公开数据集**
- COCO 数据集:<https://cocodataset.org>
- <br />
- Open Images<https://storage.googleapis.com/openimages>
**方式二:自己拍摄/收集图片**
- 确保图片清晰,目标可见
- 覆盖不同场景、光照、角度
- 统一格式为 JPG 或 PNG
### 2.4 创建数据目录结构
```bash
mkdir -p dataset/images
mkdir -p dataset/labels
```
将收集的图片放入 `dataset/images` 目录。
***
## 3. 数据标注
### 3.1 选择标注工具
推荐使用以下工具之一:
- **TjMakeBot**(在线工具,支持 AI 辅助标注):<https://www.tjmakebot.com>
- **LabelImg**(本地工具)
- **Roboflow**(在线工具)
### 3.2 使用 LabelImg 标注(本地方式)
**安装 LabelImg**
```bash
pip install labelImg
```
**启动 LabelImg**
```bash
labelImg
```
**标注步骤:**
1. 打开 LabelImg
2. 点击 "Open Dir" 选择图片目录
3. 点击 "Change Save Dir" 设置标注保存目录
4. **重要**:点击 "PascalVOC" 切换为 "YOLO" 格式
5. 使用快捷键 `W` 绘制边界框
6. 选择类别名称
7. 点击 "Save" 保存标注
8. 使用 `D` 键切换到下一张图片
### 3.3 YOLO 标注格式说明
每张图片对应一个 `.txt` 文件,格式如下:
```
class_id center_x center_y width height
```
示例:
```
0 0.5 0.5 0.3 0.4
1 0.2 0.3 0.1 0.2
```
**说明:**
- `class_id`:类别 ID(从 0 开始)
- `center_x, center_y`:边界框中心点坐标(归一化 0-1
- `width, height`:边界框宽高(归一化 0-1
***
## 4. 数据格式转换
### 4.1 验证标注文件
创建验证脚本 `validate_dataset.py`
```python
import os
from PIL import Image
def validate_yolo_dataset(dataset_dir):
images_dir = os.path.join(dataset_dir, 'images')
labels_dir = os.path.join(dataset_dir, 'labels')
errors = []
image_files = [f for f in os.listdir(images_dir) if f.endswith(('.jpg', '.png'))]
for img_file in image_files:
img_path = os.path.join(images_dir, img_file)
label_file = os.path.splitext(img_file)[0] + '.txt'
label_path = os.path.join(labels_dir, label_file)
if not os.path.exists(label_path):
errors.append(f"缺失标注文件: {label_file}")
continue
try:
img = Image.open(img_path)
img_width, img_height = img.size
except Exception as e:
errors.append(f"无法打开图片: {img_file}")
continue
with open(label_path, 'r') as f:
for line_num, line in enumerate(f, 1):
line = line.strip()
if not line:
continue
parts = line.split()
if len(parts) != 5:
errors.append(f"{label_file}: 格式错误")
continue
try:
class_id = int(parts[0])
center_x = float(parts[1])
center_y = float(parts[2])
width = float(parts[3])
height = float(parts[4])
if not (0 <= center_x <= 1 and 0 <= center_y <= 1):
errors.append(f"{label_file}: 坐标超出范围")
except ValueError:
errors.append(f"{label_file}: 数字解析错误")
if errors:
print("发现错误:")
for error in errors[:10]:
print(f" - {error}")
else:
print("验证通过!")
if __name__ == '__main__':
validate_yolo_dataset('./dataset')
```
运行验证:
```bash
python validate_dataset.py
```
### 4.2 创建数据集配置文件
创建 `dataset.yaml` 文件:
```yaml
path: ./dataset
train: images/train
val: images/val
test: images/test
nc: 3
names:
0: car
1: person
2: bicycle
```
**注意:** 根据你的实际类别修改 `nc``names`
***
## 5. 数据集划分
### 5.1 创建划分脚本
创建 `split_dataset.py`
```python
import os
import shutil
import random
def split_dataset(source_dir, train_ratio=0.7, val_ratio=0.15, test_ratio=0.15, seed=42):
random.seed(seed)
images_dir = os.path.join(source_dir, 'images')
labels_dir = os.path.join(source_dir, 'labels')
images = [f for f in os.listdir(images_dir) if f.endswith(('.jpg', '.png'))]
random.shuffle(images)
total = len(images)
train_end = int(total * train_ratio)
val_end = train_end + int(total * val_ratio)
train_images = images[:train_end]
val_images = images[train_end:val_end]
test_images = images[val_end:]
print(f"总图片数: {total}")
print(f"训练集: {len(train_images)}")
print(f"验证集: {len(val_images)}")
print(f"测试集: {len(test_images)}")
for split, img_list in [('train', train_images), ('val', val_images), ('test', test_images)]:
split_images_dir = os.path.join(source_dir, 'images', split)
split_labels_dir = os.path.join(source_dir, 'labels', split)
os.makedirs(split_images_dir, exist_ok=True)
os.makedirs(split_labels_dir, exist_ok=True)
for img in img_list:
shutil.copy(os.path.join(images_dir, img), os.path.join(split_images_dir, img))
label_name = os.path.splitext(img)[0] + '.txt'
src_label = os.path.join(labels_dir, label_name)
dst_label = os.path.join(split_labels_dir, label_name)
if os.path.exists(src_label):
shutil.copy(src_label, dst_label)
print("数据集划分完成!")
if __name__ == '__main__':
split_dataset('./dataset')
```
### 5.2 执行划分
```bash
python split_dataset.py
```
### 5.3 验证划分结果
```bash
ls dataset/images/train
ls dataset/images/val
ls dataset/images/test
```
***
## 6. 模型训练
### 6.1 创建训练脚本
创建 `train.py`
```python
from ultralytics import YOLO
import torch
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(f"使用设备: {device}")
model = YOLO('yolov8n.pt')
results = model.train(
data='dataset.yaml',
epochs=100,
imgsz=640,
batch=16,
device=device,
lr0=0.01,
patience=50,
save=True,
plots=True,
project='runs/detect',
name='my_model',
exist_ok=True,
)
print("训练完成!")
print(f"最佳模型保存在: runs/detect/my_model/weights/best.pt")
```
### 6.2 开始训练
```bash
python train.py
```
### 6.3 训练参数说明
| 参数 | 说明 | 建议值 |
| -------- | ------ | ----------- |
| epochs | 训练轮数 | 100-300 |
| imgsz | 输入图片尺寸 | 640 |
| batch | 批次大小 | 根据 GPU 内存调整 |
| lr0 | 初始学习率 | 0.01 |
| patience | 早停耐心值 | 50 |
### 6.4 模型选择建议
| 模型 | 参数量 | 速度 | 精度 | 适用场景 |
| ------- | ----- | -- | -- | ---- |
| yolov8n | 3.2M | 最快 | 较低 | 实时检测 |
| yolov8s | 11.2M | 快 | 中等 | 平衡 |
| yolov8m | 25.9M | 中等 | 较高 | 生产环境 |
| yolov8l | 43.7M | 较慢 | 高 | 高精度 |
***
## 7. 模型评估与测试
### 7.1 评估模型
创建 `evaluate.py`
```python
from ultralytics import YOLO
model = YOLO('runs/detect/my_model/weights/best.pt')
metrics = model.val(data='dataset.yaml', split='val')
print("=" * 50)
print("模型评估结果")
print("=" * 50)
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}")
print("=" * 50)
```
运行评估:
```bash
python evaluate.py
```
### 7.2 测试单张图片
创建 `predict.py`
```python
from ultralytics import YOLO
model = YOLO('runs/detect/my_model/weights/best.pt')
results = model('dataset/images/test/test_image.jpg', save=True, conf=0.25)
for result in results:
boxes = result.boxes
for i in range(len(boxes)):
class_name = model.names[int(boxes.cls[i])]
conf = boxes.conf[i]
print(f"检测到: {class_name}, 置信度: {conf:.2f}")
```
运行测试:
```bash
python predict.py
```
### 7.3 批量测试
```python
from ultralytics import YOLO
model = YOLO('runs/detect/my_model/weights/best.pt')
results = model('dataset/images/test', save=True, conf=0.25)
```
### 7.4 性能基准
| 应用场景 | mAP50 目标 | mAP50-95 目标 |
| ----- | -------- | ----------- |
| 快速原型 | > 0.5 | > 0.3 |
| 生产环境 | > 0.7 | > 0.5 |
| 高精度应用 | > 0.9 | > 0.7 |
***
## 常见问题排查
### 问题 1Loss 不下降
**解决方案:**
- 调整学习率(尝试 0.001-0.01
- 检查数据质量
- 尝试更大的模型
### 问题 2:过拟合
**解决方案:**
- 增加数据量
- 使用更小的模型
- 启用更多数据增强
### 问题 3:训练很慢
**解决方案:**
- 使用 GPU 训练
- 增大批次大小
- 减小图片尺寸
***
## 目录结构总结
完成后的目录结构:
```
project/
├── venv/ # 虚拟环境目录(不应提交到版本控制)
├── dataset/
│ ├── images/
│ │ ├── train/
│ │ ├── val/
│ │ └── test/
│ └── labels/
│ ├── train/
│ ├── val/
│ └── test/
├── dataset.yaml
├── train.py
├── evaluate.py
├── predict.py
├── split_dataset.py
└── validate_dataset.py
```
***
## 快速开始命令汇总
```bash
# 创建并激活虚拟环境
python -m venv venv
venv\Scripts\activate
# 安装依赖
pip install ultralytics
# 后续步骤
python validate_dataset.py
python split_dataset.py
python train.py
python evaluate.py
python predict.py
```
***
## 一键运行环境准备
项目已提供 `run_demo.py` 脚本,可一键完成环境搭建:
```bash
python run_demo.py
```
该脚本会自动完成:
1. 检查 Python 版本
2. 创建虚拟环境
3. 安装 ultralytics 依赖
4. 验证安装
5. 检查 GPU 支持
## 在 VS Code 中直接运行代码
### 方法一:使用 Code Runner 插件
1. 打开 VS Code,搜索并安装 `Code Runner` 插件
2. 将光标放在代码块内,点击右上角的 ▶️ 按钮运行
### 方法二:右键运行
在代码块内右键,选择 "Run Code" 或使用快捷键 `Ctrl+Alt+N`
### 方法三:终端运行
```bash
# 进入项目目录
cd .
# 激活虚拟环境
venv\Scripts\activate
# 运行脚本
python run_demo.py
python validate_dataset.py
python split_dataset.py
python train.py
```
***
祝训练顺利!