X-AnyLabeling Datasets & YOLO11 Object Detection
- 前言
- 1. 介绍
- 2. 系统环境
- 3. 安装 X-AnyLabeling 标注工具
- 3.1 从源码安装
- 3.2 从GUI运行
- 4. 制作YOLO目标检测数据集
- 4.1 准备图片
- 4.2 打标签
- 4.3 导出数据集
- 4.4 数据集拆分
- 4.5 数据集配置文件
- 5. 训练YOLO11目标检测模型
- 5.1 模型配置文件
- 5.2 训练模型
- 5.3 评估模型
- 5.4 推理模型
- 5.5 导出模型
- 6. 测试自动标注功能
- 6.1 使用YOLO11s预训练模型
- 6.2 使用SAM2分割万物模型
- 6.3 使用自己训练的模型
- 步骤1. 将模型导出ONNX格式
- 步骤2. 拷贝并修改模型配置文件
- 步骤3. 导入自定义训练的模型
前言
笔者最近刚好在配置YOLOv8和YOLO11的开发环境,需要用到图片标注工具制作自己的数据集,于是就翻阅了大量资料,找到一款非常好用的免费的半自动标注工具 X-AnyLabeling,于是本文详细记录该工具的安装、制作数据集和YOLO11模型训练的所有步骤细节。
1. 介绍
以往我们常见的有 LabelImg 和 Labelme 两款非常经典且主流的本地标注,但随着要标注的数据量越来越大,再熟练的标注大师也顶不住全手工标注了,丸辣!于是就诞生了一些半自动、全自动甚至用到大语言模型辅助的标准工具,帮助数据标注人员提高效率。
下面推荐 X-AnyLabeling 一款先进的自动标注工具,可以导入YOLO11、SAM2、PP-OCR等非常多先进的通用模型辅助打标签,支持Windows、Linux和MacOS平台,支持CPU和GPU加速模型推理,支持从图像到视频到文本等等,导出目前能见到的绝大多数的数据集格式,它即涵盖了LabelImg 和 Labelme 的所有功能,还能先标注一部分数据集,训练一个半成品模型出来,进一步辅助你自动标注完剩下的大量数据集,然后你只需要做后续的微调和审查工作,节省了大量时间和重复劳动。
X-AnyLabeling 仓库提供英文文档(EN)和中文文档(CN)便于阅读,对我这种小白就超级友好!这里十分感谢开发者的仓库维护和持续更新,目前发布的v2.4.4版本已经支持YOLO11全部类型的模型。
2. 系统环境
笔者演示的系统环境如下,仅供参考:
Windows10、i5-12490F、RTX 2070 Super
CUDA 12.4、cuDNN 8.9.7、Python 3.9、Miniconda3 24.9.2、Pycharm Community 2024.2.4
3. 安装 X-AnyLabeling 标注工具
仓库提供了两种工具安装方式,根据各自的硬件条件和需求进行选择,测试了两个都装也不影响,区别如下:
【方式一】 从源码安装:提供更完整的功能,性能更稳定,更新维护更及时。
【方式二】 从GUI运行:官方直接提供了CPU版.exe程序,一键启动点开即用,缺点是暂不支持调用GPU加速推理。
(注意:本文只提供一般性需求的安装教程,如需使用MacOS版或SAM2视频抠像等高级功能,请详细阅读官方安装指引文档探索)
3.1 从源码安装
安装前请确保系统中已安装3.8以上版本的Python,还有Anaconda或者Miniconda虚拟环境配置工具。
如果需要用到NVIDIA GPU加速,则还需要事先安装好版本相互匹配的CUDA、cuDNN。
(Tips:以上工具安装和环境配置,可以参考我前面写的的一篇YOLO11开发环境配置教程)
步骤1. 创建 conda 虚拟环境
打开Anaconda Prompt终端,默认进入base环境
# 创建一个名为“x-anylabeling”的虚拟环境,并指定了Python版本为3.9
conda create --name x-anylabeling python=3.9 -y
# 激活虚拟环境
conda activate x-anylabeling
步骤2. 配置 PyCharm 环境
新建一个项目,并且将项目的python解释器定位到刚刚创建的Conda虚拟环境
Python Interpreter 选中 x-anylabeling 这个虚拟环境之后,后面打开PyCharm终端都会自动进入到这个环境中了。
步骤3. 安装 ONNX Runtime
(注意:这一步在Conda Prompt终端激活的x-anylabeling环境中进行,或者直接打开上面配置好的PyCharm终端工具中进行安装)
安装的ONNX Runtime 的版本需大于等于 1.16.0,根据CPU和GPU的使用需求,自行选择安装版本。
其中,对于有GPU加速需求的朋友,需要确认CUDA和cuDNN版本对应兼容的ONNX Runtime版本,并安装所需的依赖库:
Ⅰ. CUDA Execution Provider (CUDA、cuDNN和ONNX Runtime的版本配对表)
Ⅱ. Get started with ONNX Runtime in Python (各种ONNX Runtime版本的安装方法)
Ⅲ. ONNX Runtime Compatibility (安装ONNX Runtime的系统配置要求)
例如笔者电脑里已安装CUDA 12.4、cuDNN 8.9.7,于是对应下面这个表就需要装 ONNX Runtime 1.18.0,看我最后的安装命令。
各种版本 ONNX Runtime 的安装方式如下:
# Install ONNX Runtime CPU(对于CPU,哪个版本都无所谓,直接装)
pip install onnxruntime
# Install ONNX Runtime GPU(默认安装适配于CUDA 12.x的版本)
pip install onnxruntime-gpu
# Install ONNX Runtime GPU (CUDA 11.x)
pip install onnxruntime-gpu --extra-index-url https://aiinfra.pkgs.visualstudio/PublicPackages/_packaging/onnxruntime-cuda-11/pypi/simple/
# Install ONNX Runtime GPU (CUDA 12.x)
pip install onnxruntime-gpu --extra-index-url https://aiinfra.pkgs.visualstudio/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple/
我已经试过上面的方法了,根本就不能自动装对,哈哈哈哈哈哈,搞得我又得卸了重装。
# 查看已安装的依赖包
pip list
# 卸载已安装的包
pip uninstall onnxruntime-gpu
所以强烈建议!直接指定你要的版本来安装:
# Install ONNX Runtime GPU(指定某个x.x.x版本安装)
pip install onnxruntime-gpu==x.x.x
# 例如以下,顺便这里指定了清华镜像站的下载源来提速
pip install onnxruntime-gpu==1.18.0 -i https://pypi.tuna.tsinghua.edu/simple
步骤4. 克隆仓库代码
git clone https://github/CVHub520/X-AnyLabeling.git
步骤5. 安装环境依赖
根据使用需求,调用前面克隆下来的项目文件夹根目录下的requirement.txt
文件进行自动安装依赖库,具体区别如下:
# 进入仓库项目文件夹
cd X-AnyLabeling
# 命令格式参考如下
pip install -r requirements-[xxx].txt
# 例如我这里选择安装适用于GPU且支持再编译的
pip install -r requirements-gpu-dev.txt
# 同样如果遇到网络问题,可以尝试指定下载源
pip install -r requirements-gpu-dev.txt -i https://pypi.tuna.tsinghua.edu/simple
步骤6. 设置环境配置
完成以上必要步骤后,使用以下命令生成资源:
pyrcc5 -o anylabeling/resources/resources.py anylabeling/resources/resources.qrc
为避免冲突,请执行以下命令卸载第三方相关包:
pip uninstall anylabeling -y
设置环境变量:(特别注意,这里不是直接复制,要改成你刚刚从git拉取下来的项目文件目录)
# Linux 或 macOS
export PYTHONPATH=/path/to/X-AnyLabeling
# Windows
set PYTHONPATH=C:\path\to\X-AnyLabeling
# 例如这里我改成我的项目文件夹中的X-AnyLabeling目录所在路径
set PYTHONPATH=E:\mycode\X-AnyLabeling\X-AnyLabeling
如果您需要 GPU 加速,应在 app_info.py
配置文件中将 __preferred_device__
字段设置为 'GPU'
。
步骤7. 运行程序
打开Pycharm终端命令行运行应用程序:
# 先进入项目文件夹内
cd X-AnyLabeling
# 运行程序
python anylabeling/app.py
3.2 从GUI运行
直接到 X-AnyLabeling仓库,往下翻一点找到v2.4.4的Assets,下载.exe软件包。
软件无需安装,双击打开直接用。
4. 制作YOLO目标检测数据集
详细的标注软件使用说明和打标签的方法,在官方仓库的 User_Guide用户手册 里找到。
这里必须划重点说明:【打标签的十个注意事项】
- 样本图像的宽高比例不能太极端,一般都不会用大于1:3甚至1:4往上的图片,不然对象被严重拉伸,无法学习特征。
- 考虑样本的分辨率是否过大,经过训练时输入模型的图像尺寸(例如640x640或640x480)压缩,还能否保证标注的对象清晰。
- 样本图像中必须包含至少一个要检测的对象,不然这张图片为空白样本就得剔除。
- 如果对象类别之间的特征差异较少,应收集更多对象形态的样本,尽可能描述清楚对象的特征,增加类别之间的特征对比度。
- 数据集中如果有多个对象类别,或者在出现比例上有严重差异,则应该尽可能增加数据集的整体数量,以提高基数。
- 想训练的精度高,首要前提就是手工打标签必须要贴合目标对象,不多框不少框,不然后续再怎么优化训练参数都白费。
- 对象太微小的、模糊拖影的、甚至人眼都无法辨别特征的、对象呈现形态太特殊超出要检测预期的,都不算作一个标签对象。
- 当对象有重叠,重叠或遮挡不是特别严重的、人眼还能看得见对象主体特征的,那被遮挡对象都得打标签。
- 每个对象必须有单独的标签,不能偷懒,对象和标签类别必须一一对应,绝对不能混淆、模棱两可。
- 标签绝不能超过样本图像的边界,不然可能会导致标签数据错乱或异常,打完标签一定要回头逐一检查,绝不可有错。
4.1 准备图片
我简单准备了60张照片用做演示,素材来自B站的老六、拆damn专家、苍蝇头、偷包侠、电击小子等等视频截图 cs_jpg.zip。
建议统一图片的格式和后缀,方便后续处理,写个脚本或者全选后重命名即可一键编号,Win10自动编号的文件名中间有空格不影响。
(Tips:你可以直接导入一个视频,软件可以用跳帧采集视频帧的方式帮你制作图片数据集。)
4.2 打标签
导入图片素材文件夹
快捷键【R】开始绘制矩形框,左上角和右下角各点一下,然后在弹框中输入对象的类别。
按住【Ctrl键】滑动鼠标滚轮,可以对图片进行缩放。 快键键【A】上一张,【D】下一张,直到全部打完。
这里有个技巧,可以开启【自动使用上一个标签】,固定一个标签类别一直标完,再回头标下一个类别,可以提高效率,减少错标率。
全部标完,记得回来检查确认是否有错漏。
标注完会自动保存同名的.json标签描述文件,避免软件崩溃导致数据丢失,下次打开软件自动读取标签。
点击左上角【工具】查看【统计总览】,可以看到标签的数量分布情况。
4.3 导出数据集
先根据前面创建标签类别的顺序,准备一个类别名称描述文件
比如我新建一个classes.txt
文件,编写内容如下:
点击软件【导出YOLO水平框标签】,选择刚刚创建的标签文件。
标签的默认导出位置就和我们的CS文件夹并列
导出的标签文件为同名的.txt格式,里面的内容我没记错的话,分别是类ID、框中心坐标XY和宽高WH(相对于原图尺寸的比例值)
4.4 数据集拆分
一般数据集都需要按比例拆分成三个部分:训练集、验证集、测试集
简单说明一下:
- 训练集和验证集在训练的过程中使用到,可以简单理解为模型只会在训练集上学习我们标注的对象特征,然后自主预测验证集的图片,用验证集的标签和预测结果比对,判断检验它自己学的对不对,然后重复这个过程很多次进行迭代模型,加深对目标对象的特征理解。
- 测试集是和训练集、验证集完全隔离的,不会参与到训练的过程中,测试集是用于我们训练完得到输出的模型后,在进行评估验证(Validate)时用到的数据,用于统计模型的检测精度和性能,帮助用户判断训练的效果的。
我参考了这篇文章,接下来新建一个用于拆分数据集的python脚本,注意里面要修改为你们的实际项目路径。
# 该脚本将YOLO目标检测的样本图片和标注数据按比例切分为三部分:训练集、验证集和测试集
import shutil
import random
import os
# 修改你的项目路径、原始图像数据和标签路径
cur_path = "E:/Project/"
image_original_path = cur_path + "cs/"
label_original_path = cur_path + "labels/"
image_format = '.png' # 样本照片的格式后缀 .jpg .png .bmp等等
# 标签拆分比例
train_percent = 0.8
val_percent = 0.1
test_percent = 0.1
# 训练集路径
train_image_path = os.path.join(cur_path, "datasets/images/train/")
train_label_path = os.path.join(cur_path, "datasets/labels/train/")
# 验证集路径
val_image_path = os.path.join(cur_path, "datasets/images/val/")
val_label_path = os.path.join(cur_path, "datasets/labels/val/")
# 测试集路径
test_image_path = os.path.join(cur_path, "datasets/images/test/")
test_label_path = os.path.join(cur_path, "datasets/labels/test/")
# 训练集目录
list_train = os.path.join(cur_path, "datasets/train.txt")
list_val = os.path.join(cur_path, "datasets/val.txt")
list_test = os.path.join(cur_path, "datasets/test.txt")
def del_file(path):
for i in os.listdir(path):
file_data = path + "\\" + i
os.remove(file_data)
def mkdir():
if not os.path.exists(train_image_path):
os.makedirs(train_image_path)
else:
del_file(train_image_path)
if not os.path.exists(train_label_path):
os.makedirs(train_label_path)
else:
del_file(train_label_path)
if not os.path.exists(val_image_path):
os.makedirs(val_image_path)
else:
del_file(val_image_path)
if not os.path.exists(val_label_path):
os.makedirs(val_label_path)
else:
del_file(val_label_path)
if not os.path.exists(test_image_path):
os.makedirs(test_image_path)
else:
del_file(test_image_path)
if not os.path.exists(test_label_path):
os.makedirs(test_label_path)
else:
del_file(test_label_path)
def clearfile():
if os.path.exists(list_train):
os.remove(list_train)
if os.path.exists(list_val):
os.remove(list_val)
if os.path.exists(list_test):
os.remove(list_test)
def main():
mkdir()
clearfile()
file_train = open(list_train, 'w')
file_val = open(list_val, 'w')
file_test = open(list_test, 'w')
total_txt = os.listdir(label_original_path)
num_txt = len(total_txt)
list_all_txt = range(num_txt)
num_train = int(num_txt * train_percent)
num_val = int(num_txt * val_percent)
num_test = num_txt - num_train - num_val
train = random.sample(list_all_txt, num_train)
# train从list_all_txt取出num_train个元素
# 所以list_all_txt列表只剩下了这些元素
val_test = [i for i in list_all_txt if not i in train]
# 再从val_test取出num_val个元素,val_test剩下的元素就是test
val = random.sample(val_test, num_val)
print("训练集数目:{}, 验证集数目:{}, 测试集数目:{}".format(len(train), len(val), len(val_test) - len(val)))
for i in list_all_txt:
name = total_txt[i][:-4]
srcImage = image_original_path + name + image_format
# srcImage = image_original_path + name + '.jpg'
srcLabel = label_original_path + name + ".txt"
if i in train:
dst_train_Image = train_image_path + name + image_format
dst_train_Label = train_label_path + name + '.txt'
shutil.copyfile(srcImage, dst_train_Image)
shutil.copyfile(srcLabel, dst_train_Label)
file_train.write(dst_train_Image + '\n')
elif i in val:
dst_val_Image = val_image_path + name + image_format
dst_val_Label = val_label_path + name + '.txt'
shutil.copyfile(srcImage, dst_val_Image)
shutil.copyfile(srcLabel, dst_val_Label)
file_val.write(dst_val_Image + '\n')
else:
dst_test_Image = test_image_path + name + image_format
dst_test_Label = test_label_path + name + '.txt'
shutil.copyfile(srcImage, dst_test_Image)
shutil.copyfile(srcLabel, dst_test_Label)
file_test.write(dst_test_Image + '\n')
file_train.close()
file_val.close()
file_test.close()
if __name__ == "__main__":
main()
注意:datasets 文件夹生成后,标签文件已绑定绝对路径,Project 目录下的所有文件路径都不可再变动。
转换后的文件目录结构如下。
Project
├───cs
├───labels
├───classes.txt
└───datasets
├───images
│ ├───test
│ ├───train
│ └───val
├───labels
│ ├───test
│ ├───train
│ └───val
├───test.txt
├───train.txt
└───val.txt
4.5 数据集配置文件
在Project目录下,用文本文档工具新建一个.yam配置文件,然后用记事本打开编辑即可。
复制以下内容进去,修改为自己的参数,然后保存。注意这里编辑的内容是大小写和空格都敏感的。
# Datasets
path: E:/Project/datasets/ # 数据集文件夹所在路径
train: train.txt # 数据集路径下的 train.txt
val: val.txt # 数据集路径下的 val.txt
test: test.txt # 数据集路径下的 test.txt
# Number of Classes
nc: 2
# Classes Name List
names:
0: CT
1: T
5. 训练YOLO11目标检测模型
YOLO11的环境配置这里不再多讲,可以参考我之前一篇配置教程,改成拉取官方的ultralytics/ultralytics仓库项目进行安装即可。
也可以参考Ultralytics官方指引文档和其他教程配置开发环境。
5.1 模型配置文件
可以从官方的yolo11.yaml文件开始构建一个新的模型结构,也可以直接下载官方的预训练模型.pt文件,地址如下:
https://github/ultralytics/assets/releases/download/v8.3.0/yolo11n.pt
https://github/ultralytics/assets/releases/download/v8.3.0/yolo11s.pt
https://github/ultralytics/assets/releases/download/v8.3.0/yolo11m.pt
下面举例前面第一种方式,进入ultralytics目录的如下位置,修改yolo11.yaml文件,将nc参数改为你要训练的标签类别数量
5.2 训练模型
在ultralytics同级目录新建一个模型训练脚本yolo_train_cs.py
,复制如下内容进去,修改成你的训练参数。
Tips 1:填写路径时的yolo11s.yaml
就是指定生成s大小的模型,n/s/m/l/x的模型同理。
Tips 2:目前v2.4.4版本的X-AnyLabeling模型库仅适配支持导入YOLO11s的模型进行自动标注辅助功能。所以这里我用s模型训练。
from ultralytics import YOLO
def train():
model = YOLO(r"ultralytics/cfg/models/11/yolo11s.yaml") # 从官方YAML文件构建一个新模型,例如填写yolo11m即可定位到m模型
# model = YOLO(r"yolo11s.pt") # 加载一个从官网下载的预训练模型
# model = YOLO(r"my_yolo11s.pt") # 加载一个之前用同样数据集训练过的模型继续训练
model.train(data=r'E:/Project/datasets.yaml', # 加载你的数据集配置文件
imgsz=640, # 输入模型的图片被resize的尺寸
epochs=1000, # 训练的迭代轮次
time=None, # 最长训练时长(小时),设置后优先级大于epochs
batch=0.8, # 批量大小,整数固定值(4/8/16)、60%显存自动模式(-1)、指定利用率自动模式(0.75)
workers=8, # 工作线程数量
device=0, # 训练设备cpu:cpu或者cuda:0/1/[0,1,2,3]
project=None, # 保存模型训练结果的项目目录名称
name=None, # 保持训练结果的子目录名称
plots=True, # 生成并保存训练和验证指标图和预测示例图,可视化模型性能和训练进度
)
if __name__ == '__main__':
train()
训练结果默认保存在ultralytics/runs/detect/train
目录下,其中weight文件夹中包含两个模型权重文件:
- best.pt 保存的是训练过程中自动验证得到分数最高的模型
- last.pt 保存的是最后一次epoch迭代的模型训练结果
至于其他图表数据怎么看,就得下次等我自己搞明白了,再出一篇文章给大家详细分析说明了。
最后两张图就是训练的效果对比,左边是我们自己打的标签框,右边是训练出来的模型实际预测框。训练样本不多,凑合着看看效果吧。
5.3 评估模型
在ultralytics同级目录新建一个模型训练脚本yolo_val_cs.py
,复制如下内容进去,修改成你的模型和评估验证参数。
import warnings
from ultralytics import YOLO
warnings.filterwarnings('ignore')
def val():
model = YOLO(r'runs/detect/train8/weights/best.pt') # 加载模型
metrics = model.val(data=r'E:/Project/datasets.yaml', # 加载数据集
imgsz=640, # 设置输入模型的图像尺寸,与训练时一致
batch=16, # 设置处理图像批大小,这个整数太大会爆显存
split='test', # 指定数据集中的测试集分支
workers=8, # 设置工作线程数量
device=0, # 设置运行设备,这里使用的是显卡
conf=0.25, # 置信度阈值,意思是置信度≥0.25的预测框都算合格
iou=0.7, # 重叠框阈值,意思是重合率≤0.7的预测框都算合格
half=False, # 使用FP16半精度计算减少内存占用提高执行效率
plots=True, # 设置是否显示统计图表
)
if __name__ == '__main__':
val()
运行程序得到以下结果:
训练的效果对比,左边是我们自己打的标签框,右边是训练出来的模型实际预测框。刚好可以看到置信度阈值和重叠率阈值的设置关系。
5.4 推理模型
在ultralytics同级目录新建一个模型训练脚本yolo_predict_cs.py
,复制如下内容进去,修改成你的模型和推理参数。
import cv2
from ultralytics import YOLO
import os
def predict():
model = YOLO(r'runs/detect/train8/weights/best.pt') # 加载模型
image_dir = r"E:\Project\datasets\images\test"
images = os.listdir(image_dir) # 获取文件夹内所有图片名称字符串到一个数组内
print("total images number:", len(images))
# 模型推理
for image in images:
frame = cv2.imread(image_dir+'\\'+image)
results = model.predict(source=frame, # 输入图像
imgsz=640, # 输入模型的图片被resize的尺寸
conf=0.35, # 最低置信度阈值
iou=0.7, # 最大重叠率阈值
device=0, # 运行设备cpu/0/1/[0,1,2,3]
half=False, # 使用FP16半精度计算,减少内存提高GPU效率
project=None, # 保存结果的项目目录名称
name=None, # 保持结果的子目录名称
stream=False, # 设置推理时采用媒体流的方式
)
for result in results:
out = result.plot() # 绘制检测结果
cv2.imshow("result", out) # 显示图片
cv2.waitKey(0) # 暂停,等待用户输入任意键继续
cv2.destroyAllWindows()
if __name__ == '__main__':
predict()
如果你想从检测结果中获取检测框的关键信息,数据提取方式可以参考如下:
你可以自己绘制检测框,或者将检测数据用到任务中,或者直接保存一个推理视频。
import cv2
from ultralytics import YOLO
import os
def predict():
model = YOLO(r'runs/detect/train8/weights/best.pt') # 加载模型
image_dir = r"E:\Project\datasets\images\test"
images = os.listdir(image_dir) # 获取文件夹内所有图片名称字符串到一个数组内
print("total images number:", len(images))
# 结果保存为视频
# fourcc = cv2.VideoWriter.fourcc('X', 'V', 'I', 'D')
# result_video = cv2.VideoWriter("out.avi", fourcc, 2,(700, 700))
# 模型预热(推理首帧处理较久,包含了模型加载进显卡缓存的时间)
for image in images:
model(image_dir+"\\"+image)
break # 只推理第一张图
# 模型推理
for image in images:
frame = cv2.imread(image_dir+"\\"+image)
results = model.predict(source=frame, # 输入图像
imgsz=640, # 输入模型的图片被resize的尺寸
conf=0.35, # 最低置信度阈值
iou=0.7, # 最大重叠率阈值
device='0', # 运行设备cpu/0/1/[0,1,2,3]
half=False, # 使用FP16半精度计算,减少内存提高GPU效率
project=None, # 保存结果的项目目录名称
name=None, # 保持结果的子目录名称
stream=False, # 设置推理时采用媒体流的方式
)
# 绘制检测结果
for result in results:
# # 官方的一键绘制检测框方法
out_plot = result.plot()
cv2.imshow("out_plot", out_plot)
# 提取检测框数据
names = result.names
cls = result.boxes.cls.tolist()
conf = result.boxes.conf.tolist()
xyxy = result.boxes.xyxy.tolist()
# 初始化绘图参数
color_1 = (0, 255, 0)
color_2 = (0, 0, 255)
bright_color = (255, 255, 255)
dark_color = (0, 0, 0)
num = len(cls)
tips_h = 18 # 文本框高度
out = frame # 从原图拷贝作为绘制结果的画布
# 遍历所有检测框对象
for j in range(num):
if cls[j] == 0:
rect_color = color_1
txt_color = dark_color
cls_id = 0
cls_name = names[cls_id]
elif cls[j] == 1:
rect_color = color_2
txt_color = bright_color
cls_id = 1
cls_name = names[cls_id]
else:
print("unknown class")
break
cls_conf = round(conf[j], 3) # 对浮点数四舍五入保留三位小数
cls_data = str(cls_id) + "-" + cls_name + "-" + str(cls_conf)
tips_w = len(cls_data) * 12
# 在图像上绘制检测框
out = cv2.rectangle(out,
(int(xyxy[j][0]), int(xyxy[j][1])),
(int(xyxy[j][2]), int(xyxy[j][3])),
rect_color, # 颜色
2) # 框线粗细
# 在图像上绘制文本底框
out = cv2.rectangle(out,
(int(xyxy[j][0]), int(xyxy[j][1]) - tips_h),
(int(xyxy[j][0]) + tips_w, int(xyxy[j][1])),
rect_color, # 颜色
-1) # 框线粗细,-1为实心
# 在图像上绘制文本信息
cv2.putText(out, # 图像画布
cls_data, # 字符内容
(int(xyxy[j][0]) + 2, int(xyxy[j][1]) - 2), # 左下角坐标
cv2.FONT_HERSHEY_SIMPLEX, # 字体格式
0.6, # 字体大小
txt_color, # 字体颜色
1) # 笔画粗细
cv2.imshow("out_draw", out)
cv2.waitKey(0)
# result_video.write(out) # 写入视频帧
# result_video.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
predict()
5.5 导出模型
以导出ONNX格式的模型为例:
from ultralytics import YOLO
def export():
model = YOLO(r'runs/detect/train8/weights/best.pt') # 加载模型
model.export(format='onnx', #导出onnx格式,默认原路径保存,例如:best.onnx
imgsz=640, # 模型的图片输入尺寸
dynamic=False, # 禁止模型动态的图片输入大小
)
if __name__ == '__main__':
export()
6. 测试自动标注功能
X-AnyLabeling官方的文档中声明的导入模型有三种途径:
- 加载内置模型,直接在软件的下拉框选择导入官方适配好的模型即可,如果遇到网络问题可以去model_zoo下载后手动导入。
- 加载已适配的用户自定义模型,也就是在model_zoo列表中有的,但是经过你自己再次训练过的模型,下面会进行演示。
- 加载未适配的用户自定义模型,也就是在model_zoo列表中没有的,这种情况需要须自行按照官方指引文档进行。
6.1 使用YOLO11s预训练模型
导入图片样本后,点击左边一栏的【AI】那个按钮,选择需要的模型下载。
(如果显示下载失败或无法调用CUDA,说明环境配置还有问题,自己回去排查,或者网络问题)
点击【运行】就会自动框选中模型训练过的对象类别,YOLO11官方模型一共有90个训练的对象类别,例如下面的person
类。
自动标注完之后还是需要手动修改标签类别的,如果框的不准或者不是你要的目标,最好还是检查清楚,手动再微调一下。
6.2 使用SAM2分割万物模型
SAM2是非常先进的分割大模型,可以用来快速抠出分割的目标,常用在实例分割任务中。
根据需要选择SAM2模型自动标注后,输出多边形、矩形框或者旋转框。
例如我这里需要给CT苍蝇头抠个全身的掩膜mask,就选择【多边形】,通过【+点】的方式在CT身上点击,没覆盖到的就多点几下。
然后点击【完成对象】,修改标签类别为CT就可以了。
6.3 使用自己训练的模型
这里主要演示如何导入自己训练的YOLO11目标检测模型。
步骤1. 将模型导出ONNX格式
参考前面第5.5节模型导出的示例程序,输出best.onnx
文件
因为软件不支持导入动态输入的模型,在导出模型时要求将参数dynamic
设置为False
。
使用Netron工具打开.onnx文件,检查模型结构,,确保模型输入和输出节点的第一个维度为1
步骤2. 拷贝并修改模型配置文件
进入X-AnyLabeling 模型库中拷贝对应的模型的.yaml配置文件。
例如拷贝YOLO11s的配置文件中的内容,在本地新建一个YOLO11s_CS.yaml
文件进行编辑。
将模型文件和配置文件放到同一个文件夹中,建议在配置文件中使用相对路径定位模型路径。
除了以上常用的参数之外,如果你只想推理模型中的部分类别,还可以设置filter_classes
字段进行类别筛选。
步骤3. 导入自定义训练的模型
发现没有更新阈值,那就手动输入设置一下,然后点击运行,推理的效果还行,可能我前面训练的数据集太少,不太准但勉强能用。
点击左侧这个‘“▶‘”按钮,就可以一次性将后面所有图片都推理出标签框了。