X-AnyLabeling 应用和 YOLO 实战教程
本教程将详细介绍如何使用 X-AnyLabeling 进行图像标注,并使用 YOLO 进行模型训练。
1. X-AnyLabeling 的安装
1.1 环境要求
- Conda 创建专门的环境
- Git(用于克隆源代码)
- pip 包管理器
conda create -n label -y # 不需要指定 python 的版本号
conda activate label
1.2 从源代码安装
步骤 1:克隆仓库
# git clone https://github.com/vietanhdev/anylabeling.git
# cd anylabeling
git clone https://github.com/CVHub520/X-AnyLabeling
cd X-AnyLabeling
步骤 2:安装依赖
# 安装基础依赖
pip install -r requirements.txt
# 如果需要 GPU 支持(推荐)
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
步骤 3:运行应用
python3 anylabeling/app.py
1.3 验证安装
启动应用后,如果看到图形界面窗口,说明安装成功。
2. X-AnyLabeling 页面操作的简单说明
2.1 主界面布局
X-AnyLabeling 的主界面包含以下主要区域:
- 左侧工具栏:标注工具(矩形、多边形、点等)
- 中央画布:显示当前图像和标注
- 右侧面板:标签管理和属性设置
- 底部状态栏:显示当前操作状态
2.2 基本操作
下一张图片
- 快捷键:
D或→(下一张),A或←(上一张),F(完成当前图片标注) - 菜单操作:
File→Next Image/Previous Image - 按钮:点击工具栏中的前进/后退按钮
Label 管理
-
创建标签:
- 点击右侧面板的
+按钮 - 输入标签名称(如:
person,car,dog) - 选择标签颜色(可选)
- 点击右侧面板的
-
编辑标签:
- 右键点击标签列表中的标签
- 选择
Edit进行修改 - 可以修改名称、颜色等属性
-
删除标签:
- 右键点击标签,选择
Delete - 或选中标签后按
Delete键
- 右键点击标签,选择
进行标注
-
矩形标注(Bounding Box):
- 选择矩形工具(快捷键
R) - 在图像上拖拽绘制矩形框
- 选择对应的标签
- 选择矩形工具(快捷键
-
多边形标注(Polygon/Segmentation):
- 选择多边形工具(快捷键
P) - 点击图像上的点创建多边形顶点
- 双击完成多边形绘制
- 选择对应的标签
- 选择多边形工具(快捷键
-
编辑标注:
- 点击已存在的标注框/多边形
- 拖拽顶点调整形状
- 右键菜单可以删除或修改属性
AI 辅助标注及位置
-
启用 AI 辅助:
- 点击工具栏中的
AI按钮,在左边的侧边栏,图标是一个圆圈包裹 AI 两个字母。 - 或使用快捷键
Ctrl + A
- 点击工具栏中的
-
AI 辅助标注位置:
- 自动标注:AI 会自动检测图像中的物体并生成标注框
- 智能建议:在手动标注时,AI 会提供标注建议
- 快速标注:批量处理多张图像
-
AI 模型选择:
- 在
Settings→AI Model中选择不同的 AI 模型 - 支持 YOLO、SAM(Segment Anything Model)等模型
- 在
3. AI 辅助标注工具的下载
一开始没有任何模型,会提示没有可用模型,这个时候只需要手动添加就可以了,选择的是 meta 下面的 Segment Anything (ViT-base quant),点击之后就会自动下载了,下载完毕之后选择使用,就会提供一些工具;点击这些工具进行使用,例如 点工具 只需要在感兴趣的地方点一下就可以自动分割,会自动计算出一个矩形框,这个时候如果没有问题就按 f 键,弹出标注框,设置标签即可。
3.1 操作流程
-
打开设置:
- 点击菜单
Settings→AI Model Settings - 或使用快捷键
Ctrl + ,
- 点击菜单
-
选择模型:
- 在模型列表中选择需要的模型(如:YOLOv8、SAM、RT-DETR 等)
- 点击
Download按钮
-
等待下载:
- 下载进度会显示在状态栏
- 模型文件较大,可能需要几分钟
-
验证下载:
- 下载完成后,模型会出现在已安装模型列表中
- 可以点击
Test按钮测试模型
3.2 下载的位置
模型文件默认保存在以下位置:
Linux/Mac:
~/.xanylabeling_data/models/
手动指定位置:
- 在设置中可以修改模型保存路径
Settings→General→Model Directory
3.3 常用 AI 模型
- YOLOv8:目标检测,速度快,精度高
- SAM (Segment Anything):图像分割,支持零样本分割
- RT-DETR:实时目标检测
- YOLOv5:经典目标检测模型
4. 标记图片并导出成 YOLO Segment 格式
4.1 使用 AI 工具完成标注任务
最开始的步骤一定是准备图片,然后将这些图片规范命名,放在一个单独的文件夹下面,加载到 X-Labeling 工作空间中,这一步是开始,也是最重要的一步。
-
准备图像:
- 将需要标注的图像放在一个文件夹中
- 支持的格式:
.jpg,.png,.bmp等
-
加载图像:
File→Open Dir选择图像文件夹- 或
File→Open打开单张图像
-
使用 AI 辅助标注:
- 点击
AI按钮启用 AI 辅助 - 选择 AI 模型(如 Meta 的 Vit-base Quant)
- AI 会自动检测并标注物体
- 手动调整不准确的标注
- 点击
-
手动补充标注:
- 对于 AI 未检测到的物体,手动添加标注
- 使用多边形工具进行精确分割标注
4.2 YOLO Segment 格式介绍
YOLO Segment 格式用于实例分割任务,包含以下内容:
目录结构:
dataset/
├── images/
│ ├── train/
│ │ ├── image1.jpg
│ │ └── image2.jpg
│ └── val/
│ └── image3.jpg
└── labels/
├── train/
│ ├── image1.txt
│ └── image2.txt
└── val/
└── image3.txt
标签文件格式(.txt):
class_id x1 y1 x2 y2 x3 y3 ... xn yn
class_id:类别ID(从0开始)x1 y1 x2 y2 ...:归一化的多边形顶点坐标(0-1之间)- 每个顶点用两个浮点数表示(x, y)
- 一行表示一个实例
示例:
0 0.5 0.3 0.7 0.3 0.7 0.6 0.5 0.6
1 0.2 0.1 0.4 0.1 0.4 0.3 0.2 0.3
4.2节有点迷惑性,事实上不应该出现在文章的这个位置,因为这和数据的标注毫无联系,应该跳过 4.2 节,等到后续导出标注完成之后再按照 4.2 节的格式整理数据集。实际上这里和 5.1 有些重复了。
4.3 导出标注
-
设置导出格式:
File→Export Annotations- 选择
YOLO格式 - 选择
Segment模式(分割模式)
-
选择导出选项:
- 选择保存路径
- 选择是否包含图像(复制图像到导出目录)
- 选择是否分离训练集和验证集
-
导出:
- 点击
Export按钮 - 导出的内容会覆盖原来同名文件夹中的所有内容,在导出的时候同时勾选出将原始图片一起导出,这样有利于后面训练数据集的构建。
- 等待导出完成
- 点击
5. 将图片和标签整理成标准训练目录 Dataset
一般来说在 ~/ 下创建一个名为 dataset 的目录作为训练数据集的根目录。
5.1 标准 YOLO 训练目录结构
将上一小节导出的内容整理成如下形式:
dataset/
├── images/
│ ├── train/ # 训练图像
│ │ ├── img1.jpg
│ │ └── img2.jpg
│ └── val/ # 验证图像
│ └── img3.jpg
└── labels/
├── train/ # 训练标签
│ ├── img1.txt
│ └── img2.txt
└── val/ # 验证标签
└── img3.txt
5.2 格式转换脚本(手动整理也是可以的)
创建 convert_to_yolo_dataset.py:
import os
import shutil
from pathlib import Path
import random
def convert_to_yolo_dataset(
source_dir,
output_dir,
train_ratio=0.8,
val_ratio=0.2
):
"""
将 X-AnyLabeling 导出的 YOLO 格式转换为标准训练目录结构
Args:
source_dir: 源目录(包含 images 和 labels 文件夹)
output_dir: 输出目录
train_ratio: 训练集比例
val_ratio: 验证集比例
"""
source_path = Path(source_dir)
output_path = Path(output_dir)
# 创建输出目录结构
(output_path / "images" / "train").mkdir(parents=True, exist_ok=True)
(output_path / "images" / "val").mkdir(parents=True, exist_ok=True)
(output_path / "labels" / "train").mkdir(parents=True, exist_ok=True)
(output_path / "labels" / "val").mkdir(parents=True, exist_ok=True)
# 获取所有图像文件
if (source_path / "images").exists():
images_dir = source_path / "images"
else:
images_dir = source_path
image_files = list(images_dir.glob("*.jpg")) + \
list(images_dir.glob("*.png")) + \
list(images_dir.glob("*.jpeg"))
# 随机打乱
random.shuffle(image_files)
# 计算分割点
total = len(image_files)
train_count = int(total * train_ratio)
# 分割数据集
train_images = image_files[:train_count]
val_images = image_files[train_count:]
# 复制文件
labels_dir = source_path / "labels" if (source_path / "labels").exists() else source_path
for img_path in train_images:
# 复制图像
shutil.copy2(img_path, output_path / "images" / "train" / img_path.name)
# 复制标签
label_path = labels_dir / f"{img_path.stem}.txt"
if label_path.exists():
shutil.copy2(label_path, output_path / "labels" / "train" / label_path.name)
for img_path in val_images:
# 复制图像
shutil.copy2(img_path, output_path / "images" / "val" / img_path.name)
# 复制标签
label_path = labels_dir / f"{img_path.stem}.txt"
if label_path.exists():
shutil.copy2(label_path, output_path / "labels" / "val" / label_path.name)
print(f"转换完成!")
print(f"训练集: {len(train_images)} 张图像")
print(f"验证集: {len(val_images)} 张图像")
if __name__ == "__main__":
# 使用示例
convert_to_yolo_dataset(
source_dir="./exported_data", # X-AnyLabeling 导出的目录
output_dir="./dataset", # 输出目录
train_ratio=0.8,
val_ratio=0.2
)
使用方法:
python convert_to_yolo_dataset.py
5.3 实践中的 dataset 结构
.
├── data.yaml
├── images
│ ├── train
│ │ ├── 微信图片_20251128132525_22.jpg
│ │ ├── 微信图片_20251128132550_23.jpg
│ │ ├── 微信图片_20251128132555_24.jpg
│ │ ├── 微信图片_20251128132558_25.jpg
│ │ ├── 微信图片_20251128132600_26.jpg
│ │ ├── 微信图片_20251128132603_27.jpg
│ │ ├── 微信图片_20251128132605_28.jpg
│ │ ├── 微信图片_20251128132607_29.jpg
│ │ ├── 微信图片_20251128132610_29.jpg
│ │ ├── 微信图片_20251128132637_38.jpg
│ │ ├── 微信图片_20251128132641_39.jpg
│ │ ├── 微信图片_20251128132644_40.jpg
│ │ ├── 微信图片_20251128132647_41.jpg
│ │ ├── 微信图片_20251128132649_42.jpg
│ │ ├── 微信图片_20251128132653_43.jpg
│ │ ├── 微信图片_20251128132655_44.jpg
│ │ └── 微信图片_20251128132700_45.jpg
│ └── val
│ ├── 微信图片_20251128132613_30.jpg
│ ├── 微信图片_20251128132617_31.jpg
│ ├── 微信图片_20251128132702_46.jpg
│ └── 微信图片_20251128132705_47.jpg
└── labels
├── train
│ ├── 微信图片_20251128132525_22.txt
│ ├── 微信图片_20251128132550_23.txt
│ ├── 微信图片_20251128132555_24.txt
│ ├── 微信图片_20251128132558_25.txt
│ ├── 微信图片_20251128132600_26.txt
│ ├── 微信图片_20251128132603_27.txt
│ ├── 微信图片_20251128132605_28.txt
│ ├── 微信图片_20251128132607_29.txt
│ ├── 微信图片_20251128132637_38.txt
│ ├── 微信图片_20251128132641_39.txt
│ ├── 微信图片_20251128132644_40.txt
│ ├── 微信图片_20251128132647_41.txt
│ ├── 微信图片_20251128132649_42.txt
│ ├── 微信图片_20251128132653_43.txt
│ ├── 微信图片_20251128132655_44.txt
│ └── 微信图片_20251128132700_45.txt
├── val
│ ├── 微信图片_20251128132613_30.txt
│ ├── 微信图片_20251128132617_31.txt
│ ├── 微信图片_20251128132702_46.txt
│ └── 微信图片_20251128132705_47.txt
└── val.cache
6 directories, 44 files
6. 为 Dataset 写一个 data.yaml
6.1 data.yaml 格式说明
data.yaml 是 YOLO 训练所需的配置文件,定义了数据集路径、类别等信息。
6.2 标准格式示例
创建 data.yaml:
# 数据集路径(相对于此 yaml 文件的路径)
path: ./dataset # 数据集根目录
train: images/train # 训练图像路径(相对于 path)
val: images/val # 验证图像路径(相对于 path)
# 类别数量
nc: 3 # number of classes
# 类别名称列表
names:
0: person # 类别 0 的名称
1: car # 类别 1 的名称
2: dog # 类别 2 的名称
6.3 完整示例
# YOLO Dataset Configuration
# 数据集配置文件
# 数据集根目录路径
path: /path/to/your/dataset
# 训练和验证数据路径(相对于 path)
train: images/train
val: images/val
# 测试集(可选)
# test: images/test
# 类别数量
nc: 5
# 类别名称(必须与标注文件中的 class_id 对应)
names:
0: person
1: bicycle
2: car
3: motorcycle
4: bus
# 下载脚本(可选,用于自动下载数据集)
# download: |
# python download.py
6.4 注意事项
-
路径设置:
- 可以使用绝对路径或相对路径
- 相对路径是相对于
data.yaml文件的位置 - 确保路径正确,否则训练时会报错
-
类别ID对应:
names中的索引必须与标注文件中的class_id对应- 类别ID从 0 开始
- 类别数量
nc必须等于names的长度
-
文件结构:
- 确保
images/train和images/val目录存在 - 确保
labels/train和labels/val目录存在 - 图像和标签文件名必须一一对应(扩展名不同)
- 确保
-
验证配置:
- 可以使用 YOLO 的验证脚本检查配置是否正确
- 确保所有路径可访问
6.5 实践中的 data.yaml
# custom_data.yaml
path: /home/ubuntu/dataset # 数据集根目录
# 图像路径
train: images/train
val: images/val
# test: images/test # 可选
# 类别信息
nc: 2
names:
0: 'coffee'
1: 'coke'
# 下载命令/URL(可选)
# download: https://ultralytics.com/assets/coco128.zip
7. 使用 Python 命令下载训练所需模型权重
7.1 YOLOv8 模型下载
X-AnyLabeling 不直接提供模型权重下载服务,需要手动下载或使用脚本下载。
方法 1:使用 ultralytics 库下载
from ultralytics import YOLO
# 下载预训练模型
model = YOLO('yolov8n-seg.pt') # nano 版本,分割模型
# 可选模型:
# - yolov8n-seg.pt (nano, 最小最快)
# - yolov8s-seg.pt (small)
# - yolov8m-seg.pt (medium)
# - yolov8l-seg.pt (large)
# - yolov8x-seg.pt (xlarge, 最大最准确)
python3 -C "from ultralytics import YOLO; model = YOLO('yolov8n-seg.pt') # nano 版本,分割模型"
方法 2:手动下载
访问 Ultralytics 官方仓库 下载权重文件。
7.2 权重文件保存位置
默认位置:
# Linux/Mac
~/.ultralytics/weights/
X-AnyLabeling 模型位置:
# Windows
C:\Users\<用户名>\.anylabeling\models\
# Linux/Mac
~/.anylabeling/models/
7.3 下载脚本示例
创建 download_weights.py:
from ultralytics import YOLO
import os
def download_yolo_weights(model_name='yolov8n-seg.pt', save_dir=None):
"""
下载 YOLO 模型权重
Args:
model_name: 模型名称
save_dir: 保存目录(如果为 None,使用默认位置)
"""
# 创建保存目录
if save_dir:
os.makedirs(save_dir, exist_ok=True)
save_path = os.path.join(save_dir, model_name)
else:
save_path = None
# 下载模型
model = YOLO(model_name)
if save_path:
# 复制到指定位置
import shutil
default_path = model.ckpt_path
shutil.copy2(default_path, save_path)
print(f"模型已保存到: {save_path}")
else:
print(f"模型已下载到默认位置: {model.ckpt_path}")
return model.ckpt_path
if __name__ == "__main__":
# 下载不同大小的模型
models = [
'yolov8n-seg.pt', # nano
'yolov8s-seg.pt', # small
'yolov8m-seg.pt', # medium
]
for model_name in models:
print(f"正在下载 {model_name}...")
download_yolo_weights(model_name)
print(f"{model_name} 下载完成\n")
运行脚本:
pip install ultralytics
python download_weights.py
注意事项:
- 模型文件较大(几十MB到几百MB),需要稳定的网络连接
- 下载后的权重文件可以复制到 X-AnyLabeling 的模型目录使用
- 确保有足够的磁盘空间
7.4 实际上使用的方法
上面几种方法都可以下载到对应的 pt 文件,但是在上一次成功的经验中,我是将 Ultralytics 的源代码下载了下来,然后使用脚本指令的方式下载想要的 pt 文件,这样下载下来的 pt 文件就直接放在了 Ultralytics 源代码的根目录下面了。
# 1. 克隆Ultralytics仓库
git clone https://github.com/ultralytics/ultralytics.git
# 2. 进入目录
cd ultralytics
# 3. 安装依赖
pip install -e .
# 4. 用Python脚本下载pt文件(直接下载到当前目录)
python -c "from ultralytics import YOLO; model = YOLO('yolov8n.pt')"
# 或者下载特定模型
python -c "from ultralytics import YOLO; YOLO('yolov8s-seg.pt')" # 分割模型
8. 在 X-AnyLabeling 中训练模型
8.1 准备工作
-
确保数据集已准备好:
- 数据集目录结构正确
data.yaml配置文件已创建;(据上所述,我的 data.yaml 是放在~/dataset中的- 图像和标签文件一一对应)
-
选择预训练模型:
- 选择 Ultralytics 源码根目录中通过指令下载得到的,名为
yolov8n.pt的权重。
- 选择 Ultralytics 源码根目录中通过指令下载得到的,名为
8.2 训练步骤
步骤 1:打开训练界面
- 点击菜单
Tools→Train Model - 或使用快捷键
Ctrl + T - 训练界面会弹出
步骤 2:配置训练参数
在训练界面中设置以下参数:
基本设置:
- Model Type:选择
YOLOv8 Segment(分割模型) - Model Size:选择模型大小(n/s/m/l/x)
n(nano):最小最快,适合快速实验s(small):平衡速度和精度m(medium):较好的精度l(large):高精度x(xlarge):最高精度,但最慢
数据集设置:
- Dataset Path:选择
data.yaml文件的路径 - Train/Val Split:如果数据集中未分离,可以设置比例(默认 0.8/0.2)
训练参数:
- Epochs:训练轮数(建议 100-300)
- Batch Size:批次大小(根据GPU内存调整,如 8, 16, 32)
- Image Size:输入图像尺寸(如 640, 1280)
- Learning Rate:学习率(默认自动调整)
- Device:选择训练设备(CPU/GPU)
高级设置:
- Patience:早停耐心值(如果验证损失不下降,提前停止)
- Save Period:保存检查点的周期
- Project Name:项目名称
- Experiment Name:实验名称
步骤 3:开始训练
- 检查所有参数设置
- 点击
Start Training按钮 - 训练过程会显示在日志窗口中
步骤 4:监控训练过程
训练过程中可以查看:
- Loss 曲线:训练损失和验证损失
- Metrics:mAP、精度、召回率等指标
- 训练进度:当前 epoch、剩余时间等
- GPU 使用率:如果使用 GPU 训练
8.3 训练界面说明
主要区域:
- 左侧面板:参数配置区域
- 中央区域:训练日志和进度显示
- 右侧面板:实时指标和图表
- 底部状态栏:当前训练状态
快捷键:
Ctrl + S:保存当前配置Ctrl + P:暂停/继续训练Ctrl + Q:停止训练
8.4 训练技巧
-
从小模型开始:
- 先用
yolov8n-seg.pt快速验证流程 - 确认无误后再使用大模型
- 先用
-
调整批次大小:
- GPU 内存不足时减小 batch size
- 可以尝试使用梯度累积
-
数据增强:
- 在
data.yaml中可以配置数据增强参数 - 如翻转、旋转、缩放等
- 在
-
学习率调整:
- 如果损失不下降,可以降低学习率
- 使用学习率调度器
9. 训练结果及转换成 ONNX 格式输出模型
9.1 训练结果位置
训练完成后,模型和结果保存在以下位置:
默认保存路径:
# Linux/Mac
~/.xanylabeling_data/trainer/Ultralytics/runs/segment/exp/weights
目录结构:
runs/segment/exp/
├── weights/
│ ├── best.pt # 最佳模型权重(验证集上表现最好)
│ └── last.pt # 最后一轮的模型权重
├── results.png # 训练结果图表
├── confusion_matrix.png # 混淆矩阵
├── F1_curve.png # F1 曲线
├── PR_curve.png # 精确率-召回率曲线
├── args.yaml # 训练参数配置
└── results.csv # 训练指标 CSV 文件
9.2 模型评估
训练完成后,可以查看:
- 最佳模型:
weights/best.pt- 在验证集上表现最好的模型 - 训练曲线:
results.png- 损失和指标曲线 - 混淆矩阵:
confusion_matrix.png- 类别预测混淆情况 - PR 曲线:
PR_curve.png- 精确率-召回率曲线
9.3 转换为 ONNX 格式
ONNX(Open Neural Network Exchange)是一种开放的模型格式,可以在不同框架间转换和部署。
方法 1:在 X-AnyLabeling 中转换
-
打开导出界面:
- 训练完成后,在训练界面点击
Export按钮 - 或选择
Tools→Export Model
- 训练完成后,在训练界面点击
-
选择导出格式:
- 在格式列表中选择
ONNX - 选择要导出的模型(
best.pt或last.pt)
- 在格式列表中选择
-
设置导出参数:
- Input Size:输入图像尺寸(如 640)
- Dynamic:是否支持动态输入尺寸
- Simplify:是否简化模型(推荐)
- Opset Version:ONNX opset 版本(默认 12)
-
导出:
- 点击
Export按钮 - 等待转换完成
- 转换后的
.onnx文件会保存在模型目录中
- 点击
方法 2:使用 Python 脚本转换
创建 export_to_onnx.py:
from ultralytics import YOLO
import os
def export_to_onnx(model_path, output_path=None, imgsz=640, simplify=True):
"""
将 YOLO 模型转换为 ONNX 格式
Args:
model_path: .pt 模型文件路径
output_path: 输出 ONNX 文件路径(如果为 None,自动生成)
imgsz: 输入图像尺寸
simplify: 是否简化模型
"""
# 加载模型
model = YOLO(model_path)
# 导出为 ONNX
success = model.export(
format='onnx',
imgsz=imgsz,
simplify=simplify,
opset=12, # ONNX opset 版本
dynamic=False, # 是否支持动态输入
)
if success:
# 获取导出后的文件路径
if output_path is None:
output_path = model_path.replace('.pt', '.onnx')
print(f"模型已成功导出为 ONNX 格式: {output_path}")
return output_path
else:
print("导出失败")
return None
if __name__ == "__main__":
# 使用示例
model_path = r"C:\Users\<用户名>\.anylabeling\runs\segment\exp\weights\best.pt"
export_to_onnx(model_path)
运行脚本:
python export_to_onnx.py
9.4 ONNX 模型验证
转换完成后,可以验证 ONNX 模型:
import onnx
import onnxruntime as ort
import numpy as np
# 加载 ONNX 模型
onnx_model = onnx.load("best.onnx")
onnx.checker.check_model(onnx_model)
# 创建推理会话
session = ort.InferenceSession("best.onnx")
# 获取输入输出信息
input_name = session.get_inputs()[0].name
output_names = [output.name for output in session.get_outputs()]
print(f"输入名称: {input_name}")
print(f"输出名称: {output_names}")
# 测试推理
dummy_input = np.random.randn(1, 3, 640, 640).astype(np.float32)
outputs = session.run(output_names, {input_name: dummy_input})
print("ONNX 模型验证成功!")
10. 保存的位置以及测试、推理脚本
10.1 模型保存位置总结
训练模型:
# Linux/Mac
~/.xanylabeling_data/trainer/Ultralytics/runs/segment/exp/weights/
├── best.pt
└── last.pt
导出的 ONNX 模型:
# 会被保存在模型权重同一目录
<weights_dir>/best.onnx
10.2 测试脚本
创建 test_model.py:
from ultralytics import YOLO
from pathlib import Path
import cv2
import numpy as np
def test_model(model_path, image_path, conf_threshold=0.25, save_dir=None):
"""
测试训练好的模型
Args:
model_path: 模型文件路径(.pt 或 .onnx)
image_path: 测试图像路径或目录
conf_threshold: 置信度阈值
save_dir: 结果保存目录
"""
# 加载模型
model = YOLO(model_path)
# 如果是目录,处理所有图像
image_path = Path(image_path)
if image_path.is_dir():
image_files = list(image_path.glob("*.jpg")) + \
list(image_path.glob("*.png"))
else:
image_files = [image_path]
# 创建保存目录
if save_dir:
save_path = Path(save_dir)
save_path.mkdir(parents=True, exist_ok=True)
else:
save_path = None
# 处理每张图像
for img_file in image_files:
# 推理
results = model.predict(
source=str(img_file),
conf=conf_threshold,
save=True,
save_dir=str(save_path) if save_path else None,
show_labels=True,
show_conf=True,
line_width=2
)
# 打印结果
for result in results:
print(f"\n图像: {img_file.name}")
print(f"检测到 {len(result.boxes)} 个目标")
# 打印每个检测结果
for i, box in enumerate(result.boxes):
cls = int(box.cls[0])
conf = float(box.conf[0])
print(f" 目标 {i+1}: 类别={cls}, 置信度={conf:.2f}")
if __name__ == "__main__":
# 使用示例
model_path = r"C:\Users\<用户名>\.anylabeling\runs\segment\exp\weights\best.pt"
test_image = "./test_images" # 测试图像目录或单张图像路径
test_model(
model_path=model_path,
image_path=test_image,
conf_threshold=0.25,
save_dir="./test_results"
)
脚本说明:
- 加载模型:使用
YOLO()加载训练好的模型 - 批量处理:支持单张图像或整个目录
- 结果保存:自动保存标注后的图像
- 信息输出:打印检测到的目标数量和详细信息
10.3 推理脚本(用于实际应用)
创建 inference.py:
from ultralytics import YOLO
import cv2
import numpy as np
from pathlib import Path
class YOLOSegmentInference:
"""YOLO 分割模型推理类"""
def __init__(self, model_path, conf_threshold=0.25, device='cuda'):
"""
初始化推理器
Args:
model_path: 模型路径(.pt 或 .onnx)
conf_threshold: 置信度阈值
device: 推理设备('cuda' 或 'cpu')
"""
self.model = YOLO(model_path)
self.conf_threshold = conf_threshold
self.device = device
def predict_image(self, image_path, save_path=None, show=False):
"""
对单张图像进行推理
Args:
image_path: 图像路径
save_path: 保存路径(可选)
show: 是否显示结果
Returns:
results: 检测结果
"""
# 推理
results = self.model.predict(
source=image_path,
conf=self.conf_threshold,
device=self.device,
verbose=False
)
# 绘制结果
annotated_frame = results[0].plot()
# 保存结果
if save_path:
cv2.imwrite(save_path, annotated_frame)
print(f"结果已保存到: {save_path}")
# 显示结果
if show:
cv2.imshow("Detection Result", annotated_frame)
cv2.waitKey(0)
cv2.destroyAllWindows()
return results
def predict_video(self, video_path, output_path=None, show=False):
"""
对视频进行推理
Args:
video_path: 视频路径
output_path: 输出视频路径(可选)
show: 是否显示结果
Returns:
results: 检测结果
"""
# 推理
results = self.model.predict(
source=video_path,
conf=self.conf_threshold,
device=self.device,
save=output_path is not None,
project=Path(output_path).parent if output_path else None,
name=Path(output_path).stem if output_path else "predict",
verbose=False
)
if output_path:
print(f"结果视频已保存到: {output_path}")
return results
def predict_webcam(self, camera_id=0, show=True):
"""
实时摄像头推理
Args:
camera_id: 摄像头ID(默认0)
show: 是否显示结果
"""
cap = cv2.VideoCapture(camera_id)
while True:
ret, frame = cap.read()
if not ret:
break
# 推理
results = self.model.predict(
source=frame,
conf=self.conf_threshold,
device=self.device,
verbose=False
)
# 绘制结果
annotated_frame = results[0].plot()
# 显示
if show:
cv2.imshow("Real-time Detection", annotated_frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
def get_detection_info(self, results):
"""
提取检测信息
Args:
results: 模型推理结果
Returns:
detections: 检测信息列表
"""
detections = []
for result in results:
boxes = result.boxes
masks = result.masks
for i in range(len(boxes)):
# 获取边界框信息
box = boxes[i]
cls = int(box.cls[0])
conf = float(box.conf[0])
xyxy = box.xyxy[0].cpu().numpy() # [x1, y1, x2, y2]
# 获取分割掩码(如果有)
mask = None
if masks is not None and i < len(masks.data):
mask = masks.data[i].cpu().numpy()
detections.append({
'class_id': cls,
'confidence': conf,
'bbox': xyxy.tolist(),
'mask': mask.tolist() if mask is not None else None
})
return detections
if __name__ == "__main__":
# 使用示例
# 初始化推理器
model_path = r"C:\Users\<用户名>\.anylabeling\runs\segment\exp\weights\best.pt"
inferencer = YOLOSegmentInference(
model_path=model_path,
conf_threshold=0.25,
device='cuda' # 或 'cpu'
)
# 1. 图像推理
print("=== 图像推理 ===")
results = inferencer.predict_image(
image_path="./test_image.jpg",
save_path="./result_image.jpg",
show=True
)
# 获取检测信息
detections = inferencer.get_detection_info(results)
print(f"检测到 {len(detections)} 个目标")
for i, det in enumerate(detections):
print(f" 目标 {i+1}: 类别={det['class_id']}, 置信度={det['confidence']:.2f}")
# 2. 视频推理
# print("=== 视频推理 ===")
# inferencer.predict_video(
# video_path="./test_video.mp4",
# output_path="./result_video.mp4",
# show=True
# )
#
# 3. 批量推理
# print("=== 批量推理 ===")
# inferencer.predict_batch(
# image_dir="./test_images/",
# output_dir="./results/",
# save_txt=True # 保存检测结果到txt文件
# )
10.4 推理脚本详细说明
10.4.1 类初始化参数
model_path:模型权重文件路径(.pt 或 .onnx)conf_threshold:置信度阈值(0-1),低于此值的检测会被过滤device:推理设备,'cuda'(GPU)或'cpu'iou_threshold:NMS的IoU阈值,用于去除重叠的检测框
10.4.2 主要方法
-
predict_image():单张图像推理image_path:输入图像路径save_path:保存结果图像路径(可选)show:是否显示结果(默认False)
-
predict_video():视频推理video_path:输入视频路径output_path:输出视频路径show:是否实时显示(默认False)
-
predict_batch():批量图像推理image_dir:图像目录output_dir:结果保存目录save_txt:是否保存检测结果到txt文件
-
get_detection_info():获取检测信息- 返回检测结果列表,每个结果包含:
class_id:类别IDconfidence:置信度bbox:边界框坐标 [x1, y1, x2, y2]mask:分割掩码(如果可用)
- 返回检测结果列表,每个结果包含:
10.5 使用 ONNX 模型推理
如果导出了 ONNX 格式模型,可以使用 ONNX Runtime 进行推理:
import onnxruntime as ort
import cv2
import numpy as np
class ONNXInference:
def __init__(self, onnx_path, conf_threshold=0.25):
"""
使用 ONNX 模型进行推理
Args:
onnx_path: ONNX 模型路径
conf_threshold: 置信度阈值
"""
self.conf_threshold = conf_threshold
self.session = ort.InferenceSession(onnx_path)
self.input_name = self.session.get_inputs()[0].name
def preprocess(self, image):
"""图像预处理"""
# 调整大小到模型输入尺寸(通常是640x640)
img = cv2.resize(image, (640, 640))
# 转换为RGB
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 归一化到0-1
img = img.astype(np.float32) / 255.0
# 转换为CHW格式
img = np.transpose(img, (2, 0, 1))
# 添加batch维度
img = np.expand_dims(img, axis=0)
return img
def postprocess(self, outputs, original_shape):
"""后处理:解析模型输出"""
# outputs 是模型输出的原始结果
# 需要根据具体的模型输出格式进行解析
# 这里是一个简化的示例
detections = []
# ... 解析逻辑 ...
return detections
def predict(self, image_path):
"""预测单张图像"""
image = cv2.imread(image_path)
original_shape = image.shape
# 预处理
input_data = self.preprocess(image)
# 推理
outputs = self.session.run(None, {self.input_name: input_data})
# 后处理
detections = self.postprocess(outputs, original_shape)
return detections
# 使用示例
if __name__ == "__main__":
onnx_path = r"C:\Users\<用户名>\.anylabeling\runs\segment\exp\weights\best.onnx"
inferencer = ONNXInference(onnx_path)
results = inferencer.predict("./test_image.jpg")
print(f"检测到 {len(results)} 个目标")
10.6 性能优化建议
-
使用GPU加速:
- 确保安装了CUDA版本的PyTorch
- 设置
device='cuda'
-
批量推理:
- 对于多张图像,使用批量推理比单张推理更高效
- 可以设置合适的batch size
-
模型量化:
- 使用INT8量化可以显著提升推理速度
- 精度损失通常很小
-
TensorRT优化(NVIDIA GPU):
- 将ONNX模型转换为TensorRT格式
- 可以获得更快的推理速度
10.7 实践中使用的脚本文件的内容
# check.py
from ultralytics import YOLO
import glob
# 加载训练好的最佳模型
model = YOLO('/home/ubuntu/xanylabeling_data/trainer/ultralytics/runs/segment/exp/weights/best.pt')
# 在测试集上验证
results = model.val(
data='/home/ubuntu/dataset/data.yaml',
split='val' # 使用验证集
)
print(f"mAP50: {results.box.map50:.3f}") # 检测精度
print(f"mAP50-95: {results.box.map:.3f}") # 综合精度
# infer.py
from ultralytics import YOLO
import glob
import torch
# 设置PyTorch默认使用GPU
# torch.cuda.set_device(0) # 使用第一个GPU
# 加载训练好的最佳模型
model = YOLO('/home/ubuntu/xanylabeling_data/trainer/ultralytics/runs/segment/exp/weights/best.pt')
# 单张图片预测
results = model('/home/ubuntu/dataset/images/train/微信图片_20251128132525_22.jpg')
# results[0].show() # 显示结果
results[0].save('result.jpg') # 保存结果
# 只输出检测到的物体名称
detected_objects = []
for result in results:
for box in result.boxes:
class_id = int(box.cls[0])
class_name = result.names[class_id]
detected_objects.append(class_name)
if detected_objects:
print("📋 检测到的物体:")
for obj in set(detected_objects): # 使用set去重
count = detected_objects.count(obj)
print(f" {obj}: {count}个")
else:
print("❌ 没有检测到任何物体")
# # 批量预测
# results = model(['图片1.jpg', '图片2.jpg', '图片3.jpg'])
# for i, r in enumerate(results):
# r.save(f'result_{i}.jpg')
11. 常见问题与解决方案
11.1 训练相关问题
问题1:训练时内存不足
- 解决方案:
- 减小batch size
- 减小图像尺寸
- 使用更小的模型(如yolov8n)
问题2:训练loss不下降
- 解决方案:
- 检查数据集标注是否正确
- 调整学习率
- 增加训练轮数
- 检查数据增强是否过度
问题3:验证集精度很低
- 解决方案:
- 检查训练集和验证集的数据分布是否一致
- 增加训练数据量
- 调整数据增强策略
11.2 推理相关问题
问题1:推理速度慢
- 解决方案:
- 使用GPU加速
- 使用更小的模型
- 减小输入图像尺寸
- 使用ONNX或TensorRT优化
问题2:检测结果不准确
- 解决方案:
- 调整置信度阈值
- 检查模型是否在相似场景上训练
- 考虑重新训练或微调模型
问题3:内存占用过高
- 解决方案:
- 减小batch size
- 使用CPU推理(虽然慢但内存占用小)
- 处理完一张图像后释放内存
11.3 数据相关问题
问题1:标注格式错误
- 解决方案:
- 检查YOLO格式是否正确
- 确保坐标已归一化(0-1之间)
- 检查类别ID是否从0开始
问题2:图像和标签不匹配
- 解决方案:
- 确保图像和标签文件名一致(扩展名不同)
- 检查文件是否在正确的目录中
- 使用脚本验证文件对应关系
12. 进阶技巧
12.1 数据增强策略
在 data.yaml 中可以配置数据增强:
# 数据增强配置
augment:
hsv_h: 0.015 # 色调增强
hsv_s: 0.7 # 饱和度增强
hsv_v: 0.4 # 明度增强
degrees: 10 # 旋转角度
translate: 0.1 # 平移
scale: 0.5 # 缩放
flipud: 0.0 # 上下翻转概率
fliplr: 0.5 # 左右翻转概率
mosaic: 1.0 # Mosaic增强概率
mixup: 0.0 # Mixup增强概率
12.2 模型集成
训练多个模型并集成结果可以提高精度:
from ultralytics import YOLO
import numpy as np
# 加载多个模型
models = [
YOLO('best_model1.pt'),
YOLO('best_model2.pt'),
YOLO('best_model3.pt'),
]
def ensemble_predict(image_path, models, conf_threshold=0.25):
"""模型集成预测"""
all_results = []
for model in models:
results = model(image_path, conf=conf_threshold)
all_results.append(results[0])
# 集成策略:投票或平均
# 这里简化处理,实际需要更复杂的集成逻辑
return all_results[0] # 返回第一个模型的结果作为示例
12.3 模型剪枝与量化
from ultralytics import YOLO
# 加载模型
model = YOLO('best.pt')
# 导出为INT8量化模型
model.export(format='onnx', imgsz=640, int8=True)
# 导出为TensorRT格式(需要NVIDIA GPU)
model.export(format='engine', imgsz=640)
13. 参考资料
教程完成! 参考这份文档可以:
- 安装和使用 X-AnyLabeling 进行图像标注
- 使用 AI 辅助标注提高效率
- 导出 YOLO 格式的标注数据
- 准备标准的数据集结构
- 训练 YOLO 分割模型
- 导出和转换模型格式
- 使用训练好的模型进行推理
14. 难点总结
- 将标注图片时候的标签和 data.yaml 中的内容对齐比较麻烦,容易出错。
- 将 dataset 的目录结构与 data.yaml 中的内容对齐比较麻烦,容易出错。
- 知道怎么下载训练时使用的 pt 模型很重要,容易和 AI 标注时使用的模型混淆。
- 总的来说,需要熟练的掌握数据集的构造结构,标签的格式,yaml 文件怎么写,初始权重文件怎么下载;然后才是怎么标注。
5629

被折叠的 条评论
为什么被折叠?



