用 YOLOv8 做试卷试题区域检测的环境与训练
前言
纸质或扫描试卷上的「试题分割」在工程上常先做目标检测:为每道大题或小题画矩形框,再按框裁图或送入 OCR。
本文说明如何用 Ultralytics YOLOv8 在本地完成环境配置与训练,不展开标注工具细节与 OCR 后处理。
依赖安装与训练命令使用 uv 管理虚拟环境与包版本。
Python 最低版本以你的 pyproject.toml 中 requires-python 为准,建议使用 3.10+ 并与依赖声明保持一致。
CUDA 版 PyTorch 是否由 uv sync 直接解析到,取决于索引与平台;有独显时请对照 PyTorch 官网 与 uv 文档 做补充配置。
依赖
安装 uv
若本机尚未安装 uv,可选用官方推荐方式或包管理器安装(任选其一即可,具体以 Astral 安装说明 为准)。
在已具备 Python 的环境中,用 pip 安装 uv 的示例命令如下。
1 | python -m pip install uv |
同步依赖
推荐在项目根目录通过 pyproject.toml 声明依赖(如 ultralytics、fastapi、uvicorn 等)。
在 pyproject.toml 同级目录执行 uv sync,会创建或更新 .venv 并安装全部项目依赖,无需手写一长串 pip install。
下面命令表示进入你的项目目录后一次性同步依赖。
1 | cd your/project/backend |
若当前目录尚未初始化项目,可先创建 pyproject.toml 并写入 ultralytics 等依赖,再执行 uv sync 得到可训练环境。
依赖清单
按你给的项目依赖,可按职责归类如下。
训练核心
ultralytics>=8.4.41:YOLOv8 训练、验证、预测主包。
图像处理
opencv-python-headless>=4.13.0.92:无 GUI 环境下图像处理与解码。pillow>=12.2.0:图片读写与基础处理。
API 服务
fastapi>=0.136.1:HTTP API 框架。uvicorn[standard]>=0.46.0:ASGI 服务启动器。python-multipart>=0.0.26:处理上传图片表单。
配置管理
pydantic-settings>=2.14.0:环境变量与配置管理。
下面是与该项目对齐的 pyproject.toml 片段。
1 | [project] |
写好依赖后执行 uv sync,再用 uv run 运行训练脚本即可。
检查 PyTorch 与 GPU
安装完成后建议用 uv run 在项目虚拟环境里执行 Python,避免误用系统全局解释器。
下面一小段用于确认 torch 与 ultralytics 已导入,并打印 CUDA 是否可用。
1 | import torch |
将上面脚本存为 check_cuda.py 后可用 uv run python check_cuda.py 执行;若仅为一次性检查,也可用 uv run python -c "import torch; print(torch.cuda.is_available())"。
Python信息
激活虚拟环境
1 | .venv\Scripts\activate |
版本
1 | python -V |
位数
1 | python -c "import platform; print(platform.architecture())" |
路径
1 | python -c "import sys; print(sys.executable)" |
使用 GPU
若你按默认方式安装后训练仍走 CPU,通常是当前环境里的 torch 不是 CUDA 版本。
切换到 GPU 的关键是安装与你本机驱动匹配的 CUDA 版 torch,并在训练时指定 device=0 或 device=cuda:0。
- 先确认系统可识别 NVIDIA 显卡并且驱动正常。
- 执行
nvidia-smi,若命令不可用或无显卡信息,先完成驱动安装再继续。
下面命令用于检查显卡驱动状态。
1 | nvidia-smi |
- 在项目目录移除当前
torch相关包,避免 CPU 版残留。 - 使用对应 CUDA 索引重新安装
torch、torchvision、torchaudio。
下面示例使用 cu124 索引,安装前请按你机器环境改成正确版本。
1 | uv remove torch torchvision torchaudio |
- 安装完成后再次检查 CUDA 是否可用。
- 若
torch.cuda.is_available()仍为False,优先检查 CUDA 版本与驱动是否匹配。
下面命令用于验证 torch 是否识别 GPU 以及当前 CUDA 版本。
1 | uv run python -c "import torch; print(torch.cuda.is_available(), torch.version.cuda); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'no gpu')" |
- 训练时显式传入
device=0或--device 0。 - 若你使用训练脚本参数,建议同时保留
batch可调,防止显存不足。
下面分别给出 CLI 与脚本两种训练写法。
1 | uv run yolo detect train model=yolov8n.pt data=data/dataset/data.yaml device=0 |
为了避免后续 uv sync 又装回 CPU 版,你可以在 pyproject.toml 中固定 torch 来源索引。
下面片段示例了 tool.uv.index 与 tool.uv.sources 的常见写法。
1 | [[tool.uv.index]] |
添加后执行 uv sync,即可按该索引解析 torch 系列包。
实现
数据目录
YOLOv8 检测任务约定「图片」与「标签」分 train / val(可选 test),标签为与图片同名的 .txt 文件。
推荐将数据放在 data/dataset/ 下,与 data.yaml 同层。
下面给出一份通用目录骨架示例。
1 | data/dataset/ |
若你不沿用该路径,也可采用任意根目录名,只要与 data.yaml 里 path、train、val 一致即可。
1 | datasets/exam_questions/ |
images/train 与 labels/train 中主文件名一一对应(扩展名分别为图片格式与 .txt),验证集同理。
标注格式
每个 labels/*.txt 中一行表示一个框,共 5 个数字:class_id x_center y_center width height,且均为相对整张图的 0~1 归一化 坐标。class_id 从 0 开始;若只检测「题目块」一类,可始终为 0。
下面是一行标签的示例含义说明(数值为虚构示例,仅演示格式)。
1 | 0 0.512 0.305 0.42 0.08 |
表示类别 0 的一个框,中心约在图像正中偏上,宽高约为图宽高的 42% 与 8%。
标注可用 Label Studio、CVAT、labelImg 等工具,导出为 YOLO 格式后复制到上面对应目录。
数据集配置
在数据集根目录旁或项目内新建 data.yaml,声明路径、类别数与类别名。path 建议写绝对路径或相对于你运行命令时的当前目录的明确相对路径,避免训练时找不到图片。
可先准备一个 data.yaml 模板,再按实际路径与类别修改。
下面示例中 nc 为类别数,names 为类别名列表;单类检测时 nc: 1 即可。
1 | path: datasets/exam_questions |
多类时增大 nc 并按顺序列出 names。
训练
使用预训练权重可加快收敛,例如 yolov8n.pt(nano,速度快)、yolov8s.pt 等。
推荐在项目中提供 training/train_yolo.py 调用 Ultralytics API,并用 uv run 固定解释器与依赖版本。
脚本默认在有 CUDA 时使用 device=0,否则使用 CPU,并会打印警告,避免无 GPU 时误传 device=0 直接报错。
下面命令在项目根目录执行,使用默认数据配置与训练超参(可用 --epochs、--imgsz、--batch、--model、--device 等覆盖)。
1 | cd your/project/backend |
建议在训练脚本里通过 project 与 name 统一管理输出目录,最佳权重一般为 weights/best.pt;若对接 API,可复制到固定路径或通过环境变量配置模型路径。
若你更习惯官方 CLI,也可在已 uv sync 的环境中用下面等价方式启动训练(注意当前工作目录与 data.yaml 路径要一致)。
下面命令与脚本默认超参类似,将 data.yaml 换成你的实际路径即可。
1 | uv run yolo detect train model=yolov8n.pt data=data/dataset/data.yaml epochs=100 imgsz=640 batch=16 device=0 |
无 GPU 时请传 device=cpu 或依赖 train_yolo.py 的自动回退,并把 batch 调小以免内存不足。
未使用自定义脚本时,Ultralytics 默认产物多在 runs/detect/train/ 下的 weights/best.pt。
验证与预测
训练结束后可用同一 data.yaml 在验证集上算 mAP,用于对比不同实验。
1 | uv run yolo detect val model=data/runs/detect/paper_train/weights/best.pt data=data/dataset/data.yaml |
对单张扫描卷预测并保存画框结果时,指定图片路径与保存目录即可(模型路径按你实际 runs 目录调整)。
1 | uv run yolo detect predict model=data/runs/detect/paper_train/weights/best.pt source=path/to/page.jpg save=True |
若项目提供 FastAPI 推理接口,可在服务目录执行 uv run python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000,Windows 下若遇包路径问题可设置 PYTHONPATH 为当前目录或编写启动脚本统一处理。
若需部署到边缘设备,可在官方文档中查阅 export 为 ONNX、TensorRT 等格式的用法,本文不展开。
验证
环境是否就绪:在项目目录执行 uv sync 无报错,且 uv run python training/train_yolo.py --data ... 能跑通、loss 正常下降、无「找不到图片或标签」路径报错。
数据是否规范:随机打开几张 labels 中的 .txt,确认坐标均在 0~1 且 train/val 文件名成对存在。
训练是否过拟合:对比 train 与 val 的指标曲线,若验证集明显变差可减少轮数或增强数据增强强度。
总结
- 安装 uv,在项目目录执行
uv sync,用uv run python运行脚本与检查 GPU。 - 按
images/{train,val}与labels/{train,val}组织数据(推荐使用data/dataset/),标签为 YOLO 归一化格式。 - 编写或复制
data.yaml,指向数据根目录并声明nc与names。 - 使用
uv run python training/train_yolo.py --data data/dataset/data.yaml(或uv run yolo detect train ...),根据显存调整batch与imgsz。 - 用
uv run yolo detect val/predict或 API 检查指标与框是否贴合试题区域,再进入裁图或 OCR 流程。
试卷反光、装订线、跨栏排版会增加漏检与框粘连,需要在数据采集与标注阶段尽量覆盖真实版式,必要时增加类别或改用更大模型。