赞
踩
目录
1.4 创建最终训练需要的train.txt和val.txt文件
论文:https://arxiv.org/abs/2207.02696
代码:https://github.com/WongKinYiu/yolov7
在实际使用过程中,我用的YOLOAir库,和YOLOv7源码使用方法是一样的
yoloair2:https://github.com/iscyy/yoloair2
- .
- ├── cfg(存放yaml文件)
- │ ├── baseline
- │ ├── deploy
- │ ├── training
- │ └── improved
- ├── configs(也存放了yaml文件,但经过了改进)
- │ ├── attention
- │ ├── attention_v7
- │ ├── backbone
- │ ├── head-Improved
- │ └── ......
- ├── data(数据集信息和模型训练超参数)
- │ ├── coco.yaml
- │ ├── coco128.yaml
- │ ├── hyp.scratch.custom.yaml
- │ ├── hyp.scratch.p5.yaml
- │ ├── hyp.scratch.p6.yaml
- │ └── hyp.scratch.tiny.yaml
- ├── deploy
- │ └── triton-inference-server
- │ ├── data
- │ │ ├── dog.jpg
- │ │ └── dog_result.jpg
- │ ├── boundingbox.py
- │ ├── client.py
- │ ├── labels.py
- │ ├── processing.py
- │ ├── render.py
- │ └── README.md
- ├── figure(一些图片)
- ├── inference(存放detect用的图片)
- │ └── images
- ├── models(存放网络结构)
- │ ├── Models
- │ │ ├── Attention
- │ │ └── **.py
- │ ├── Detect
- │ ├── __init__.py
- │ ├── common.py
- │ ├── commonv5.py
- │ ├── experimental.py
- │ ├── module.py
- │ └── yolo.py
- ├── runs(模型训练时的输出)
- ├── scripts(获得COCO 数据集)
- │ └── get_coco.sh
- ├── utils
- │ ├── aws
- │ │ ├── __init__.py
- │ │ ├── mime.sh
- │ │ ├── resume.py
- │ │ └── userdata.sh
- │ ├── google_app_engine
- │ │ ├── additional_requirements.txt
- │ │ ├── app.yaml
- │ │ └── Dockerfile
- │ ├── wandb_logging
- │ │ ├── __init__.py
- │ │ ├── log_dataset.py
- │ │ └── wandb_utils.py
- │ ├── __init__.py
- │ ├── activations.py(激活函数)
- │ ├── add_nms.py
- │ ├── autoanchor.py
- │ ├── datasets.py(数据的读取和加载)
- │ ├── general.py
- │ ├── google_utils.py
- │ ├── loss.py(损失函数)
- │ ├── metrics.py(衡量指标)
- │ ├── plots.py(画图)
- │ └── torch_utils.py
- ├── train_aux.py(使用较大的预训练权重)
- ├── train.py
- ├── test.py(测试)
- ├── detect.py(检测)
- ├── export.py
- ├── hubconf.py
- ├── LICENSE.md
- ├── README.md
- ├── README_EN.md
- └── requirements.txt
(仅自己训练过程中去了解过的内容)
- if __name__ == '__main__':
- parser = argparse.ArgumentParser()
- parser.add_argument('--weights', type=str, default='weight\yolov7.pt', help='initial weights path') # 初始化权重文件,如果有预训练模型,可以直接在此加载
- parser.add_argument('--cfg', type=str, default='cfg/training\yolov7.yaml', help='model.yaml path') # 网络结构配置文件
- parser.add_argument('--data', type=str, default='data\WindTurbineBlades.yaml', help='data.yaml path') # 训练数据集配置文件
- parser.add_argument('--hyp', type=str, default='data/hyp.scratch.p5.yaml', help='hyperparameters path') # 超参数配置文件
- parser.add_argument('--epochs', type=int, default=100) # 训练迭代次数
- parser.add_argument('--batch-size', type=int, default=32, help='total batch size for all GPUs') # 训练批次大小
- parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='[train, test] image sizes') # 训练图片大小
- parser.add_argument('--rect', action='store_true', help='rectangular training') # 是否采用矩形训练,默认False
- parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training') # 是否继续进行训练,如果设置成True,那么会自动寻找最近训练权重文件
- parser.add_argument('--nosave', action='store_true', help='only save final checkpoint') # 不保存权重文件,默认False
- parser.add_argument('--notest', action='store_true', help='only test final epoch') # 不进行test,默认False
- parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check') # 不自动调整anchor,默认False
- parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters') # 是否进行超参数优化,默认是False,开启该选项,会加大训练时间,一般不需要
- parser.add_argument('--bucket', type=str, default='', help='gsutil bucket') # 谷歌云盘bucket,一般不会用到
- parser.add_argument('--cache-images', action='store_true', help='cache images for faster training') # 是否提前将训练数据进行缓存,默认是False
- parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training') # 训练的时候是否选择图片权重进行训练
- parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu') # 训练所使用的设备
- parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%%') # 是否进行多尺度训练,默认False
- parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class') # 训练数据集是否只有一类
- parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer') # 是否使用adam优化器
- parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode') # 是否使用跨卡同步BN,在DDP模式使用
- parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify') # DDP参数
- parser.add_argument('--workers', type=int, default=0, help='maximum number of dataloader workers') # dataloader的最大worker数量
- parser.add_argument('--project', default='runs/train', help='save to project/name') # 训练结果保存路径
- parser.add_argument('--entity', default=None, help='W&B entity') # wandb库对应的东西,一般不用管
- parser.add_argument('--name', default='exp', help='save to project/name') # 训练结果保存文件夹名称
- parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment') # 判断下训练结果保存路径是否存在,如果存在的话,就不用重新创建
- parser.add_argument('--quad', action='store_true', help='quad dataloader') # 作用是兼顾速度和精度,选择折中的方案
- parser.add_argument('--linear-lr', action='store_true', help='linear LR') # 用于对学习速率进行调整,默认为 false,含义是通过余弦函数来降低学习率。
- parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon') # 是否做标签平滑,防止出现过拟合
- parser.add_argument('--upload_dataset', action='store_true', help='Upload dataset as W&B artifact table') # wandb库对应的东西
- parser.add_argument('--bbox_interval', type=int, default=-1, help='Set bounding-box image logging interval for W&B') # wandb库对应的东西
- parser.add_argument('--save_period', type=int, default=-1, help='Log model after every "save_period" epoch') # 用于记录训练日志信息
- parser.add_argument('--artifact_alias', type=str, default="latest", help='version of dataset artifact to be used') # 这一行参数表达的是想实现但还未实现的一个内容,忽略即可
- parser.add_argument('--freeze', nargs='+', type=int, default=[0], help='Freeze layers: backbone of yolov7=50, first3=0 1 2') # 冻结训练,默认不冻结
- opt = parser.parse_args()
- # Resume
- wandb_run = check_wandb_resume(opt)
- if opt.resume and not wandb_run: # resume an interrupted run
- ckpt = opt.resume if isinstance(opt.resume, str) else get_latest_run() # specified or most recent path
- assert os.path.isfile(ckpt), 'ERROR: --resume checkpoint does not exist'
- apriori = opt.global_rank, opt.local_rank
- with open(Path(ckpt).parent.parent / 'opt.yaml') as f:
- opt = argparse.Namespace(**yaml.load(f, Loader=yaml.SafeLoader)) # replace
- opt.cfg, opt.weights, opt.resume, opt.batch_size, opt.global_rank, opt.local_rank = '', ckpt, True, opt.total_batch_size, *apriori # reinstate
- logger.info('Resuming training from %s' % ckpt)
- else:
- # opt.hyp = opt.hyp or ('hyp.finetune.yaml' if opt.weights else 'hyp.scratch.yaml')
- opt.data, opt.cfg, opt.hyp = check_file(opt.data), check_file(opt.cfg), check_file(opt.hyp) # check files
- assert len(opt.cfg) or len(opt.weights), 'either --cfg or --weights must be specified'
- opt.img_size.extend([opt.img_size[-1]] * (2 - len(opt.img_size))) # extend to 2 sizes (train, test)
- opt.name = 'evolve' if opt.evolve else opt.name
- opt.save_dir = increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok | opt.evolve) # increment run
若训练过程中训练中断,将Resume改为True,程序会自动寻找最后一轮的权重,然后继续训练。
check_wandb_resume()检查训练是否恢复,wandb是一个用于深度学习实验跟踪、可视化和协作的工具和平台。
- # Train
- logger.info(opt)
- if not opt.evolve:
- tb_writer = None # init loggers
- if opt.global_rank in [-1, 0]:
- prefix = colorstr('tensorboard: ')
- logger.info(f"{prefix}Start with 'tensorboard --logdir {opt.project}', view at http://localhost:6006/")
- tb_writer = SummaryWriter(opt.save_dir) # Tensorboard
- train(hyp, opt, device, tb_writer)
-
- # Evolve hyperparameters (optional) # tc
- else:
- ......
判断是否进行超参数优化,一般都是False;else后面的是超参数优化的参数,这之后的代码全是关于超参数优化的
if opt.global_rank in [-1, 0]检查是否使用分布式训练,-1表示没有,global_rank默认为-1。该条件语句内容是对Tensorboard进行设置。
train()函数,开始深度学习模型的训练
- # parameters
- nc: 80 # number of classes
- depth_multiple: 1.0 # model depth multiple
- width_multiple: 1.0 # layer channel multiple
-
- # anchors
- anchors:
- - [12,16, 19,36, 40,28] # P3/8
- - [36,75, 76,55, 72,146] # P4/16
- - [142,110, 192,243, 459,401] # P5/32
depth_multiple:控制模型深度,与number相乘(红色框位置),表示该层重复的次数
width_multiple:控制输出通道数,与args第一个参数相乘(黄色框位置)
from:表示其输入来自哪一层。
-1表示该层输入是上一层的输出,-2表示该层输入是上上层的输出,以此类推。若为正数则为正数第几层。[-1, -3, -5, -6]为倒数第一层、倒数第三层、倒数第五层、倒数第六层的输出。
number:表示该层的层数
module:表示使用的模块
args:表示模块的参数
从左到右为:输出通道数,卷积核大小,卷积核步长
- # yolov7 backbone
- backbone:
- # [from, number, module, args]
- [[-1, 1, Conv, [32, 3, 1]], # 0
-
- [-1, 1, Conv, [64, 3, 2]], # 1-P1/2
- [-1, 1, Conv, [64, 3, 1]],
-
- [-1, 1, Conv, [128, 3, 2]], # 3-P2/4
- [-1, 1, Conv, [64, 1, 1]], # 下面表示的就是ELAN模块
- [-2, 1, Conv, [64, 1, 1]],
- [-1, 1, Conv, [64, 3, 1]],
- [-1, 1, Conv, [64, 3, 1]],
- [-1, 1, Conv, [64, 3, 1]],
- [-1, 1, Conv, [64, 3, 1]],
- [[-1, -3, -5, -6], 1, Concat, [1]],
- [-1, 1, Conv, [256, 1, 1]], # 11
- if __name__ == '__main__':
- parser = argparse.ArgumentParser()
- parser.add_argument('--weights', nargs='+', type=str, default='runs\train\exp\weights\best.pt', help='model.pt path(s)') # 训练好的权重
- parser.add_argument('--source', type=str, default='inference', help='source') # file/folder, 0 for webcam 测试的图片/图片文件夹/摄像头接口
- parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)') # 图片大小
- parser.add_argument('--conf-thres', type=float, default=0.25, help='object confidence threshold') # 置信度的阈值
- parser.add_argument('--iou-thres', type=float, default=0.45, help='IOU threshold for NMS') # iou阈值
- parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
- parser.add_argument('--view-img', action='store_true', help='display results') # 是否展示测试结果
- parser.add_argument('--save-txt', action='store_true', help='save results to *.txt') # 是否保存测试的标签文件
- parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels') # 是否保存测试时目标的置信度,要和save-txt一起使用
- parser.add_argument('--nosave', action='store_true', help='do not save images/videos') # 是否保存测试图像
- parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3') # 是否只检测特定的某一类或几类,如classes 0就只检测数据集中yolo标签为0的
- parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS') # 增强版的nms
- parser.add_argument('--augment', action='store_true', help='augmented inference')
- parser.add_argument('--update', action='store_true', help='update all models')
- parser.add_argument('--project', default='runs\detect', help='save results to project/name') # 结果保存路径
- parser.add_argument('--name', default='exp', help='save results to project/name') # 保存的文件夹名字
- parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
- parser.add_argument('--no-trace', action='store_true', help='don`t trace model')
该函数在utils/plots.py中
- def plot_one_box(x, img, color=None, label=None, line_thickness=3):
- # Plots one bounding box on image img
- # 计算了绘制线条的粗细
- tl = line_thickness or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1 # line/font thickness
- color = color or [random.randint(0, 255) for _ in range(3)]
- # 计算了边界框的两个对角点的坐标c1和c2,将x中的坐标信息四舍五入为整数,用于在图像上绘制边界框
- c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))
- # 使用OpenCV的cv2.rectangle函数在图像上绘制一个矩形边界框
- cv2.rectangle(img, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)
- if label: # 是否提供了标签文本
- # 计算了标签文本的字体线条粗细
- tf = max(tl - 1, 1) # font thickness
- # cv2.getTextSize()函数能得到文字绘制出来将有多大
- t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
- c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3
- # 绘制一个填充矩形,用于容纳标签文本。这样可以在标签文本的位置上创建一个背景,使文本更容易阅读
- cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA) # filled
- # 将标签文本添加到图像上,参数为:图像,标签文本、文本框的左下角、字体、字体大小、颜色、字体线条粗细、线型
- cv2.putText(img, label, (c1[0], c1[1] - 2), 0, tl / 3, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)
x:边界框坐标的列表,(x_min, y_min, x_max, y_max),表示左上角和右下角的坐标
img:要绘制边界框的图像
color:边界框和标签的颜色,默认是随机的
label:表示要添加到边界框上的标签文本
line_thickness:线条粗细,默认为3。设为None线条粗细就跟随图像大小变化
本人标注得到的数据集是VOC格式的
- VOC
- ├── Annotations 标注(XML文件)
- └── JPEGImages 图像
(!!!要将‘.../VOC’改为自己的路径)
- '''第一步:将xml转化成txt'''
- import shutil
- import os.path
- import xml.etree.ElementTree as ET
-
-
- # 1. 将这个地方改成自己类别的列表
- class_names = ['**', '**', '**']
- # 2. 将路径修改
- xmldir='.../VOC/Annotations/'
- imagedir=".../VOC/JPEGImages/"
- txtdir='.../VOC/xml2txt/'
-
- xmlpath=os.path.join(xmldir)# 原xml路径
- imagepath=os.path.join(imagedir)# 原img路径
- txtpath=os.path.join(txtdir)# 转换后txt文件存放路径
-
- files = []
- if not os.path.exists(txtpath):
- os.makedirs(txtpath)
- else:
- shutil.rmtree(txtpath)
- os.makedirs(txtpath)
-
- image_list=os.listdir(imagepath)
- postfixes = set(['.' + i.split('.')[1] for i in image_list]) #考虑到可能有不同后缀的图片,提取所有后缀
-
- for root, dirs, files in os.walk(xmlpath): #用来
- None
- number = len(files)
- i = 0
- delete=[]
- while i < number:
-
- filename = files[i][0:-4]
- xml_name = filename + ".xml"
- txt_name = filename + ".txt"
- xml_file_name = os.path.join(xmlpath,xml_name)
- txt_file_name = os.path.join(txtpath,txt_name)
- try:
- xml_file = open(xml_file_name, 'r', encoding='utf-8') #注意加个utf8编码就是,不然会报gbk的错
- tree = ET.parse(xml_file)
- root = tree.getroot()
- # filename = root.find('name').text
-
- # image_name = root.find('filename').text
- w = int(root.find('size').find('width').text)
- h = int(root.find('size').find('height').text)
-
- f_txt = open(txt_file_name, 'w+')
- content = ""
-
- first = True
-
- for obj in root.iter('object'):
-
- name = obj.find('name').text
- class_num = class_names.index(name)
- # class_num = 0
-
- xmlbox = obj.find('bndbox')
-
- x1 = int(xmlbox.find('xmin').text)
- x2 = int(xmlbox.find('xmax').text)
- y1 = int(xmlbox.find('ymin').text)
- y2 = int(xmlbox.find('ymax').text)
-
- if first:
- content += str(class_num) + " " + \
- str((x1 + x2) / 2 / w) + " " + str((y1 + y2) / 2 / h) + " " + \
- str((x2 - x1) / w) + " " + str((y2 - y1) / h)
- first = False
- else:
- content += "\n" + \
- str(class_num) + " " + \
- str((x1 + x2) / 2 / w) + " " + str((y1 + y2) / 2 / h) + " " + \
- str((x2 - x1) / w) + " " + str((y2 - y1) / h)
-
- # print(str(i / (number - 1) * 100) + "%\n")
- print(content)
- f_txt.write(content)
- f_txt.close()
- xml_file.close()
- i += 1
-
- except ZeroDivisionError as zeroE:
- print(xml_name+'转化失败!')
- i += 1
-
- # #利用os库把xml_name文件复制到test文件夹下
- # shutil.move(xmldir + xml_name, 'test/' + xml_name)
- # shutil.move(imagedir + filename+'.jpg', 'test/' + filename+'.jpg')
-
-
- # 删除对应的label和images
- os.remove(os.path.join(xmlpath, xml_name))
- print(xml_name + '删除成功!')
- for postfix in postfixes:
- if (filename + postfix) in image_list:
- img_name = filename + postfix
- os.remove(os.path.join(imagepath, img_name))
- print(img_name + '删除成功!')
- delete.append((img_name, xml_name))
- i += 1
-
- print('总图片数量:',number)
- print(f'成功转化{number-len(delete)}张图片')
- print(f'共删除{len(delete)}张图片和标签:')
- for each in delete:
- print(each)
- '''第二步:划分train.txt,val.txt,test.txt
- 注意trainval.txt是作为辅助'''
- import os
- import random
- import shutil
-
- random.seed(0)
- # 1. 将路径修改为自己的
- xmlfilepath = '.../VOC/Annotations/'
- saveBasePath = '.../VOC/ImageSets/Main/'
- if not os.path.exists(saveBasePath):
- os.makedirs(saveBasePath)
- else:
- shutil.rmtree(saveBasePath)
- os.makedirs(saveBasePath)
- # ----------------------------------------------------------------------#
- # 想要增加测试集修改trainval_percent
- # train_percent不需要修改
- # ----------------------------------------------------------------------#
- trainval_percent = 0.9
- train_percent = 0.8
-
- temp_xml = os.listdir(xmlfilepath)
- total_xml = []
- for xml in temp_xml:
- if xml.endswith(".xml"):
- total_xml.append(xml)
-
- num = len(total_xml)
- list = range(num)
- tv = int(num * trainval_percent)
- tr = int(tv * train_percent)
- trainval = random.sample(list, tv)
- train = random.sample(trainval, tr)
-
- print("train and val size", tv)
- print("traub suze", tr)
-
- if not os.path.exists(saveBasePath):
- os.mkdir(saveBasePath)
- ftrainval = open(os.path.join(saveBasePath, 'trainval.txt'), 'w')
- ftest = open(os.path.join(saveBasePath, 'test.txt'), 'w')
- ftrain = open(os.path.join(saveBasePath, 'train.txt'), 'w')
- fval = open(os.path.join(saveBasePath, 'val.txt'), 'w')
-
- for i in list:
- name = total_xml[i][:-4] + '\n'
- if i in trainval:
- ftrainval.write(name)
- if i in train:
- ftrain.write(name)
- else:
- fval.write(name)
- else:
- ftest.write(name)
-
- ftrainval.close()
- ftrain.close()
- fval.close()
- ftest.close()
- '''第三步:复制出图片和标签,生成yolov7需要的文件夹格式
- ----images
- --train
- --val
- --test(可选)
- ----labels
- --train
- --val
- --test(可选)'''
-
- import os
- import shutil
- from tqdm import tqdm
-
- SPLIT_PATH = '.../VOC/ImageSets/Main/'
- IMGS_PATH = ".../VOC/JPEGImages/"
- TXTS_PATH = ".../VOC/xml2txt/"
-
- TO_IMGS_PATH = '.../VOC/images'
- TO_TXTS_PATH = '.../VOC/labels'
-
- data_split = ['train.txt', 'val.txt', 'test.txt']
- to_split = ['train', 'val', 'test']
-
- image_list=os.listdir(IMGS_PATH)
- postfixes = set(['.' + i.split('.')[1] for i in image_list]) #考虑到可能有不同后缀的图片,提取所有后缀
-
- for index, split in enumerate(data_split):
- split_path = os.path.join(SPLIT_PATH, split)
-
- to_imgs_path = os.path.join(TO_IMGS_PATH, to_split[index])
- if not os.path.exists(to_imgs_path):
- os.makedirs(to_imgs_path)
- else:
- shutil.rmtree(to_imgs_path)
- os.makedirs(to_imgs_path)
-
- to_txts_path = os.path.join(TO_TXTS_PATH, to_split[index])
- if not os.path.exists(to_txts_path):
- os.makedirs(to_txts_path)
- else:
- shutil.rmtree(to_txts_path)
- os.makedirs(to_txts_path)
-
- f = open(split_path, 'r')
- count = 1
-
- for line in tqdm(f.readlines(), desc="{} is copying".format(to_split[index])):
- # 复制图片
- for postfix in postfixes:
- if (line.strip()+ postfix) in image_list:
- img_name=line.strip()+ postfix
- src_img_path = os.path.join(IMGS_PATH, img_name)
- dst_img_path = os.path.join(to_imgs_path,img_name)
- if os.path.exists(src_img_path):
- shutil.copyfile(src_img_path, dst_img_path)
- else:
- print("error file: {}".format(src_img_path))
-
- # 复制txt标注文件
- src_txt_path = os.path.join(TXTS_PATH, line.strip() + '.txt')
- dst_txt_path = os.path.join(to_txts_path, line.strip() + '.txt')
- if os.path.exists(src_txt_path):
- shutil.copyfile(src_txt_path, dst_txt_path)
- else:
- print("error file: {}".format(src_txt_path))
- '''第四步:创建出最终训练需要的train.txt和val.txt文件 '''
- import os
- def listdir(path, list_name): # 传入存储的list
- for file in os.listdir(path):
- file_path = os.path.join(path, file)
- if os.path.isdir(file_path):
- listdir(file_path, list_name)
- else:
- list_name.append(file_path)
-
-
- list_name = []
- train_path = '.../VOC/images/train' # 文件夹路径,把images下的train/val/test(可选)文件夹处理就行 。注意这里开头的/不能少!!!
- listdir(train_path, list_name)
- print(list_name)
-
- with open('.../VOC/train.txt', 'w') as f: # 要存入的txt
- write = ''
- for i in list_name:
- write = write + str(i) + '\n'
- f.write(write)
-
-
- list_name = []
- val_path = '.../VOC/images/val' # 文件夹路径,把images下的train/val/test(可选)文件夹处理就行 。注意这里开头的/不能少!!!
- listdir(val_path, list_name)
- print(list_name)
- with open('.../VOC/val.txt', 'w') as f2: # 要存入的txt
- write = ''
- for i in list_name:
- write = write + str(i) + '\n'
- f2.write(write)
VOC ├── Annotations 所有的图像标注信息(XML文件) ├── JPEGImages 所有图像文件 ├── ImageSets │ └── Main │ ├── train.txt 训练集 │ ├── val.txt 验证集 │ ├── trainval.txt 训练集+验证集 │ └── test.txt 测试集 ├── images │ ├── train │ ├── val │ └── test ├── labels │ ├── train │ ├── val │ └── test ├── xml2txt YOLO格式标注 ├── train.txt 用于训练的train.txt └── val.txt 用于训练的val.txt
根据自己所选的网络选择预训练权重,也可以为空(即不使用预训练模型)
选择网络结构,同时要修改对应yaml文件中的内容
- # parameters
- nc: 80 # number of classes 这里要修改为自己的类别数
- depth_multiple: 1.0 # model depth multiple
- width_multiple: 1.0 # layer channel multiple
-
- # anchors 根据自己需要看要不要修改
- anchors:
- - [12,16, 19,36, 40,28] # P3/8
- - [36,75, 76,55, 72,146] # P4/16
- - [142,110, 192,243, 459,401] # P5/32
数据集配置文件,将路径改为自己需要的,同时修改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: coco128 # dataset root dir
- train: .../VOC/train.txt # 数据集准备1.4中生成的
- val: .../VOC/val.txt # 数据集准备1.4中生成的
- # test: # test images (optional)
-
- # Classes
- nc: 80 # number of classes 修改为自己的类别数
- names: ['**', '**', '**'] # class names 修改为自己的类别,要和数据集准备1.1部分类别顺序一致
网络超参数,路径改为自己需要的对应yaml文件
训练时用的设备,没有gpu就写cpu,有就写编号
训练结果保存路径,一般不用改,要想放到别的文件夹下就改成自己的路径
是否多线程读取数据,越大cpu读取速度越快。
单张图像太大的时候可以填大一点,一般为0、2、4、8、16
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。