目录
4、训练模型权重 YOLOv9.pt 重新参数化轻量转为 YOLOv9-converted.pt
1、提示:AttributeError: 'FreeTypeFont' object has no attribute 'getsize'
4、运行detect.py提示:AttributeError: 'list' object has no attribute 'device
一、环境安装
1、创建虚拟环境
conda create -n yolov9 python=3.8
# 激活yolov9 env
conda activate yolov9
2、安装依赖库
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
如果是已经存在的torch环境安装,可以在requirements.txt文件中删掉torch后安装(避免安装的不是GPU版本)
二、数据集准备
1、数据集的文件名
在代码根目录下,新建一个datasets的文件夹,并对这个文件夹新建下面三个文件夹,并放入对应的数据。
- Annotations里面存放标签xml文件。
- JPEGImage 里面存放原始图片。
- labels文件夹里面存放的是标签txt文件(YOLO用的也是这种类型的标签)。这个文件夹里的文件是通过脚本生成的。
yolo的标签格式,即:
2、划分数据集
根据代码划分训练集、验证集,且每个文件夹下面对应图像和标签
3、配置数据文件
- 类型1:直接指向图像所在(该文件夹包括图像和标签)---本人推荐采用这种方式
格式类型:
datasets/dataset_split/
├─train
│ ├──images
│ └──labels
├──test
│ ├──images
│ └──labels
└─val
├──images
└──labels
划分代码:
import os
import random
import shutil
# 原数据集目录
root_dir = 'dataset_fire/'
# 划分比例
train_ratio = 0.8
valid_ratio = 0.1
test_ratio = 0.1
# 设置随机种子
random.seed(42)
# TODo 这里按照实际数据集路径去修改
split_dir = 'dataset_fire_split/'
os.makedirs(os.path.join(split_dir, 'train/images'), exist_ok=True)
os.makedirs(os.path.join(split_dir, 'train/labels'), exist_ok=True)
os.makedirs(os.path.join(split_dir, 'val/images'), exist_ok=True)
os.makedirs(os.path.join(split_dir, 'val/labels'), exist_ok=True)
os.makedirs(os.path.join(split_dir, 'test/images'), exist_ok=True)
os.makedirs(os.path.join(split_dir, 'test/labels'), exist_ok=True)
# TODo 这里按照实际数据集路径去修改
imgpath = "JPEGImages"
labelpath = "labels"
image_files = os.listdir(os.path.join(root_dir, imgpath))
label_files = os.listdir(os.path.join(root_dir, labelpath))
# 随机打乱文件列表
combined_files = list(zip(image_files, label_files))
random.shuffle(combined_files)
image_files_shuffled, label_files_shuffled = zip(*combined_files)
# 根据比例计算划分的边界索引
train_bound = int(train_ratio * len(image_files_shuffled))
valid_bound = int((train_ratio + valid_ratio) * len(image_files_shuffled))
# 将图片和标签文件移动到相应的目录
for i, (image_file, label_file) in enumerate(zip(image_files_shuffled, label_files_shuffled)):
if i < train_bound:
shutil.move(os.path.join(root_dir, imgpath, image_file), os.path.join(split_dir, 'train/images', image_file))
shutil.move(os.path.join(root_dir, labelpath, label_file), os.path.join(split_dir, 'train/labels', label_file))
elif i < valid_bound:
shutil.move(os.path.join(root_dir, imgpath, image_file), os.path.join(split_dir, 'valid/images', image_file))
shutil.move(os.path.join(root_dir, labelpath, label_file), os.path.join(split_dir, 'valid/labels', label_file))
else:
shutil.move(os.path.join(root_dir, imgpath, image_file), os.path.join(split_dir, 'test/images', image_file))
shutil.move(os.path.join(root_dir, labelpath, label_file), os.path.join(split_dir, 'test/labels', label_file))
在datasets目录下新建数据的配置文件fire.yaml,内容如下:(直接指向数据所在地)
# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: datasets/dataset_split # dataset root dir
train: train # train images
val: val # val images
test: test # test images (optional)
# Classes
names:
0: anti-glaring_board
- 类型2:直接指向划分好的txt文件(该文件包括图像路径)
格式类型:
datasets/
├─train.txt
├─val.txt
├─test.txt
├─images
│ ├──train
│ │ ├──xxx.jpg
│ │ └──xxx.jpg
│ ├──test
│ │ ├──xxx.jpg
│ │ └──xxx.jpg
│ └──val
│ ├──xxx.jpg
│ └──xxx.jpg
└──labels
├──train
│ ├──xxx.txt
│ └──xxx.txt
├──test
│ ├──xxx.txt
│ └──xxx.txt
└──val
├──xxx.txt
└──xxx.txt
划分代码:
import os
import shutil
from sklearn.model_selection import train_test_split
import copy
# 设置数据文件夹路径
image_dir = "./images"
label_dir = "./labels"
# 获取image和label文件夹中的所有文件名
image_files = os.listdir(image_dir)
label_files = os.listdir(label_dir)
# 确保image和label文件夹中的文件数量相同
assert len(image_files) == len(label_files), "Number of image and label files must be t he same!"
# 将文件名组合为一个列表
label_files=copy.copy(image_files)
for i in range(len(label_files)):
label_files[i]=label_files[i].replace(".png",".txt")
files = list(zip(image_files, label_files))
# 划分数据为训练集和测试集(这里还包括验证集,但你可以根据需要调整比例)
train_files, temp_files = train_test_split(files, test_size=0.4, random_state=42) # 假设40%为测试集
valid_files, test_files = train_test_split(temp_files, test_size=0.5, random_state=42) # 剩下的50%中,再取50%为验证集
print("测试集长度:"+str(len(test_files)))
print("训练集长度:"+str(len(train_files)))
print("验证集长度:"+str(len(valid_files)))
# 创建目录(如果它们不存在)
os.makedirs(image_dir + "/train", exist_ok=True)
os.makedirs(image_dir + "/test", exist_ok=True)
os.makedirs(image_dir + "/val", exist_ok=True)
os.makedirs(label_dir + "/train", exist_ok=True)
os.makedirs(label_dir + "/test", exist_ok=True)
os.makedirs(label_dir + "/val", exist_ok=True)
# 移动文件到相应的目录
for img, lbl in train_files:
shutil.move(os.path.join(image_dir, img), os.path.join(image_dir + "/train", img))
shutil.move(os.path.join(label_dir, lbl), os.path.join(label_dir + "/train", lbl))
for img, lbl in test_files:
shutil.move(os.path.join(image_dir, img), os.path.join(image_dir + "/test", img))
shutil.move(os.path.join(label_dir, lbl), os.path.join(label_dir + "/test", lbl))
for img, lbl in valid_files:
shutil.move(os.path.join(image_dir, img), os.path.join(image_dir + "/val"