参考文章:YoloV6实战:手把手教你使用Yolov6进行物体检测(附数据集)_yolov6用自己的模型检测_AI浩的博客-CSDN博客
YOLO | 用YOLOv7训练自己的数据集(超详细版)_yolo训练集_夏天|여름이다的博客-CSDN博客
git clone https://github.com/WongKinYiu/yolov7
打开pycharm,在文件->设置中->python解释器->添加解释器,
在yolov7文件下找到venv/bin/python.exe,选择添加
根据提示一键安装,或者终端输入:
cd yolov7
pip install -r requirements.txt
pip install opencv-python-headless
下载YOLOV7的权重
wget https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7.pt
下载YOLOV7的训练权重
wget https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7_training.pt
新建一个权重文件夹,把上述文件移到权重文件夹下
mkdir weights
cp yolov7.pt weights/
cp yolov7_training.pt weights/
参数说明:
--weights weight/yolov7.pt # 这个参数是把已经训练好的模型路径传进去,就是刚刚下载的文件
--source inference/images # 传进去要预测的图片
找到一个公开数据集进行测试,数据集是Labelme标注的数据集,下载地址:
https://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/14003627
下载后解压到yolov7文件夹中
思路:
第一步 使用train_test_split方法切分出训练集、验证集和测试集。
第二步 调用change_2_yolo5方法将json里面的数据转为yolov5格式的txt数据,返回训练集、验证集和测试集的图片list。
第三步 创建数据集文件夹,然后将图片和txt文件copy到对应的目录下面。
新建脚本make_yolo_data.py,插入代码:
import os
import shutil
import numpy as np
import json
from glob import glob
import cv2
from sklearn.model_selection import train_test_split
from os import getcwd
def convert(size, box):
dw = 1. / (size[0])
dh = 1. / (size[1])
x = (box[0] + box[1]) / 2.0 - 1
y = (box[2] + box[3]) / 2.0 - 1
w = box[1] - box[0]
h = box[3] - box[2]
x = x * dw
w = w * dw
y = y * dh
h = h * dh
return (x, y, w, h)
def change_2_yolo5(files, txt_Name):
imag_name = []
for json_file_ in files:
json_filename = labelme_path + json_file_ + ".json"
out_file = open('%s/%s.txt' % (labelme_path, json_file_), 'w')
json_file = json.load(open(json_filename, "r", encoding="utf-8"))
# image_path = labelme_path + json_file['imagePath']
imag_name.append(json_file['imagePath'])
height, width, channels = cv2.imread(labelme_path + json_file_ + ".jpg").shape
for multi in json_file["shapes"]:
points = np.array(multi["points"])
xmin = min(points[:, 0]) if min(points[:, 0]) > 0 else 0
xmax = max(points[:, 0]) if max(points[:, 0]) > 0 else 0
ymin = min(points[:, 1]) if min(points[:, 1]) > 0 else 0
ymax = max(points[:, 1]) if max(points[:, 1]) > 0 else 0
label = multi["label"]
if xmax <= xmin:
pass
elif ymax <= ymin:
pass
else:
cls_id = classes.index(label)
b = (float(xmin), float(xmax), float(ymin), float(ymax))
bb = convert((width, height), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
# print(json_filename, xmin, ymin, xmax, ymax, cls_id)
return imag_name
def image_txt_copy(files, scr_path, dst_img_path, dst_txt_path):
"""
:param files: 图片名字组成的list
:param scr_path: 图片的路径
:param dst_img_path: 图片复制到的路径
:param dst_txt_path: 图片对应的txt复制到的路径
:return:
"""
for file in files:
img_path = scr_path + file
shutil.copy(img_path, dst_img_path + file)
scr_txt_path = scr_path + file.split('.')[0] + '.txt'
shutil.copy(scr_txt_path, dst_txt_path + file.split('.')[0] + '.txt')
if __name__ == '__main__':
classes = ["aircraft", "oiltank"]
# 1.标签路径
labelme_path = "datasets/LabelmeData/"
isUseTest = True # 是否创建test集
# 3.获取待处理文件
files = glob(labelme_path + "*.json")
files = [i.replace("\\", "/").split("/")[-1].split(".json")[0] for i in files]
trainval_files, test_files = train_test_split(files, test_size=0.1, random_state=55)
# split
train_files, val_files = train_test_split(trainval_files, test_size=0.1, random_state=55)
train_name_list = change_2_yolo5(train_files, "train")
print(train_name_list)
val_name_list = change_2_yolo5(val_files, "val")
test_name_list = change_2_yolo5(test_files, "test")
# 创建数据集文件夹。
file_List = ["train", "val", "test"]
for file in file_List:
if not os.path.exists('./datasets/images/%s' % file):
os.makedirs('./datasets/images/%s' % file)
if not os.path.exists('./datasets/labels/%s' % file):
os.makedirs('./datasets/labels/%s' % file)
image_txt_copy(train_name_list, labelme_path, './datasets/images/train/', './datasets/labels/train/')
image_txt_copy(val_name_list, labelme_path, './datasets/images/val/', './datasets/labels/val/')
image_txt_copy(test_name_list, labelme_path, './datasets/images/test/', './datasets/labels/test/')
记得在主函数中修改路径,将最后面的路径替换为自己想要保存的路径
生成结果如下,同时将数据集进行了分割
一个是yolov7-mydataset.yaml,位置在项目yolov7/cfg/training下,然后复制yolov7.yaml,粘贴改为yolov7-mydataset.yaml,然后修改类别数,就得到一个新的属于自己的配置文件。
nc为类别数,改为自己的,如下面38改为自己的类别数即可。
# parameters
nc: 38 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # layer channel multiple
另外一个是mydataset.yaml,新建位置在项目yolov7/data下,复制一个yaml文件粘贴,重命名为mydataset.yaml,更改内容如下
# Please insure that your custom_dataset are put in same parent dir with YOLOv6_DIR
train: ./datasets/images/train # train images
val: ./datasets/images/val # val images
test: ./datasets/images/test # test images (optional)
# whether it is coco dataset, only coco dataset should be set to True.
is_coco: False
# Classes
nc: 2 # number of classes
names: ['aircraft', 'oiltank'] # class names
--weights: 预训练路径,填写'' 表示不使用预训练权重
--cfg : 参数路径(./cfg/training中新建的yolov7-mydataset.yaml文件)
--data : 数据集路径(./data中新建的mydayaset.yaml文件)
--epochs : 训练轮数
--batch-size : batch大小
--device : 训练设备,cpu-->用cpu训练,0-->用GPU训练,0,1,2,3-->用多核GPU训练
--workers: maximum number of dataloader workers
--name : save to project/name
在train.py中向下找到参数位置,修改这几处参数,
parser.add_argument('--cfg', type=str, default='cfg/training/yolov7-mydatasets.yaml', help='model.yaml path')
parser.add_argument('--data', type=str, default='data/mydataset.yaml', help='data.yaml path')
parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
运行,等待训练完成。
在runs->train->exp下面可以查看结果,为训练及验证结果。
打开test.py,修改参数
注意runs/train/exp4/weights/best.pt为训练后生成的,改为自己的地址
parser = argparse.ArgumentParser(prog='test.py')
parser.add_argument('--weights', nargs='+', type=str, default='runs/train/exp4/weights/best.pt', help='model.pt path(s)')
parser.add_argument('--data', type=str, default='data/mydataset.yaml', help='*.data path')
parser.add_argument('--task', default='test', help='train, val, test, speed or study')
parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
其中,weights为刚才训练文件夹里的,data同训练
weights:训练权重的路径。
source:测试图片的路径,我这里把测试图片放在tools/images文件夹下面。
img-size:和训练的图片保持一致。
conf-thres:置信度的最小值。
iou-thres:IoU的值。
max-det:单张图片检测到目标不能超过该值。
预测试的图片:
生成的结果:
实验结束
有些路径必须写全,从/home开始,否则运行不出来。
配置了cuda等环境,但是仍然显示false,无法使用gpu训练。
替换方案:采用cpu进行训练,缺点是非常慢,需要缩小迭代次数。
仍需解决。