目录

  • 1. 文章主要内容
  • 2. 西工大数据集转换为VOC格式数据集
    • 2.1 VOC数据集结构
    • 2.2 西工大数据集
    • 2.3 转换格式
      • 2.3.1 构建与VOC类似的数据集文件结构(文件夹名可以自定义)
      • 2.3.2 数据预处理
  • 3. yolov3 spp 训练NWPU-VHR-10 dataset
    • 3.1 源码下载及其相关准备文件
    • 3.2 VOC格式数据集转换为yolo格式
  • 4. yolov3 spp 项目参数解析、如何获取best.pt以及定位到对应的epoch
    • 4.1 yolov3 spp 项目部分参数解析
    • 4.2 如何获取best.pt以及定位到对应的epoch
  • 5. 本篇小结

1. 文章主要内容

此篇博客为[目标检测实验系列]的首篇博客,该系列主要记录在目标检测实验过程中的详细步骤和所思所想,欢迎大家互相交流。

本篇博客参考的主要内容来源于
       大彤小忆–使用Python将NWPU VHR-10数据集的格式转换成VOC2007数据集的格式
       霹雳吧啦Wz–YOLOv3 SPP源码解析-1代码使用简介

本篇博客主要涉及两个主体内容。第一个:将西工大遥感数据集NWPU VHR-10的格式转为VOC通用的数据集。第二个:再次将转换后的VOC格式的数据集转变成yolov3 spp所需要格式的数据集,之后调试项目内容,达到成功跑通项目的要求。(通读本篇博客大概需要10分钟左右的时间)。

2. 西工大数据集转换为VOC格式数据集

2.1 VOC数据集结构

VOC通用数据集格式如下图所示:

特别注意以下几点内容

1.这里的箭头表示的文件夹由外到内,比如VOCdevkit文件夹包含了VOC2012文件,而VOC2012文件夹包含Annotations、ImageSets和JPEGImages

2.这里的VOC2012文件夹名字也可以换成VOC2007,代表不同的版本。事实上,只要保证整体的文件夹结构没有问题,所有的文件夹名字都可以自定义,只需要在对应的模型代码中指定好自定义的文件夹名字。

3.和Annotations、ImageSets和JPEGImages同级目录下,还有两个文件夹SegmentationClass、SegementionObject。因为这里用不到,所以不过多赘述。各个文件内容代表什么,请各位同学自己研究。

2.2 西工大数据集

特别注意:西工大数据集-(提取密码:1234)
       西工大NWPU VHR-10数据集包含10种类别,其主要结构如下图所示:
       特别注意以下几点内容

1.groud truth文件夹内容是坐标信息以及所对应的类别;positive image set文件夹内容是正样本的图片; negative image set文件夹内容是负样本的图片

2.3 转换格式

2.3.1 构建与VOC类似的数据集文件结构(文件夹名可以自定义)

本篇博客构建的文件结构如下图所示:(用于存放转换后的数据集)

2.3.2 数据预处理

因为NWPU VHR-10数据集的positive image set图片内容是从001.jpg-650.jpg,而negative image set图片内容是从001.jpg到150.jpg。首先,需要将正样本的数据和负样本的数据合并,并且重写进行顺序编号处理,改成000001.jpg-000800.jpg。其中positive image set文件夹内的图片被重命名为000001.jpg-000650.jpg,negative image set文件夹内的图片被重命名为000651.jpg-000800.jpg。
       最后将这800张图片存放在D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/JPEGImages(注意:这里的文件夹路径是自定义的,需按照每个同学文件夹的实际绝对路径填写),具体的转换代码如下所示:

import os
import shutildef imag_rename(old_path, new_path,start_number = 0):filelist = os.listdir(old_path)  # 该文件夹下所有的文件(包括文件夹)if os.path.exists(new_path) == False:os.mkdir(new_path)for file in filelist:  # 遍历所有文件Olddir = os.path.join(old_path, file)  # 原来的文件路径if os.path.isdir(Olddir):  # 如果是文件夹则跳过continuefilename = os.path.splitext(file)[0]  # 文件名filetype = os.path.splitext(file)[1]  # 文件扩展名if filetype == '.jpg':Newdir = os.path.join(new_path, str(int(filename) + start_number).zfill(6) + filetype)  # 用字符串函数zfill 以0补全所需位数shutil.copyfile(Olddir, Newdir)if __name__ == "__main__":# 解决positive image set文件夹中的重命名问题,start_number = 0old_path = "D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/positive image set/"new_path = "D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/JPEGImages"imag_rename(old_path, new_path)# 解决negative image set文件夹中的重命名问题,start_number = 650old_path = "D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/negative image set/"new_path = "D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/JPEGImages"imag_rename(old_path,new_path,start_number = 650)print("done!")

特别注意以下几点内容

1.代码需要修改的部分在main函数里面,分别是old_path、new_path一共两对。其中old_path分别对应于西工大数据集的positive image set、negative image set文件夹路径,而new_path对应于转换合并后创建的新文件夹路径,上面有提到。

接下来处理Annoatations文件夹的内容:将NWPU VHR-10数据集的ground truth文件夹内的标注信息txt文件转换为与VOC2007数据集的Annotations文件夹内的标注信息xml文件格式相同的xml文件,并重命名为000001.xml-000650.xml;由于negative image set文件夹内的图片没有对应的标注信息文件,所以生成包含图片的size信息、不包含object的bounding box信息的xml文件,并命名为000651.xml-000800.xml,并且存放在路径为D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/Annoatations下(和上面一样,这里也是自定义的路径),具体的代码如下所示:

from lxml.etree import Element,SubElement,tostring
from xml.dom.minidom import parseString
import xml.dom.minidom
import os
import sys
from PIL import Image# 处理NWPU VHR-10数据集中的txt标注信息转换成 xml文件
# 此处的path应该传入的是NWPU VHR-10数据集文件夹下面的ground truth文件夹的目录
# 即 path = "E:/Remote Sensing/Data Set/NWPU VHR-10 dataset/ground truth"
def deal(path):files=os.listdir(path)  # files获取所有标注txt文件的文件名# 此处可以自行设置输出路径  按照VOC数据集的格式,xml文件应该输出在数据集文件下面的Annotations文件夹下面outpath = "D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/Annoatations/"# 如果输出文件夹不存在,就创建它if os.path.exists(outpath) == False:os.mkdir(outpath)# 遍历所有的txt标注文件,一共650个txt文件for file in files:filename=os.path.splitext(file)[0] # 获取ground truth文件夹中标注txt文件的文件名,比如如果文件名为001.txt,那么filename = '001'sufix=os.path.splitext(file)[1]#  获取标注txt文件的后缀名 判断是否为txtif sufix=='.txt':   # 标注txt文件中每一行代表一个目标,(x1,y1),(x2,y2),class_number来表示xmins=[]    ymins=[]xmaxs=[]ymaxs=[]names=[]# num,xmins,ymins,xmaxs,ymaxs,names=readtxt(path + '/' + file)    # 调用readtxt文件获取信息,转到readtxt函数path_txt = path + '/' + file     # 获取txt标注文件的路径信息# 打开txt标注文件with open(path_txt, 'r') as f:contents = f.read()    # 将txt文件的信息按行读取到contents列表中objects=contents.split('\n') # 以换行划分每一个目标的标注信息,因为每一个目标的标注信息在txt文件中为一行 for i in range(objects.count('')): objects.remove('')    # 将objects中的空格移除num=len(objects) # 获取一个标注文件的目标个数,objects中一个元素代表的信息就是一个检测目标      # 遍历 objects列表,获取每一个检测目标的五维信息for objecto in objects:     xmin=objecto.split(',')[0]   # xmin = '(563'xmin=xmin.split('(')[1]   # xmin = '563' 可能存在空格xmin=xmin.strip()  # strip函数去掉字符串开头结尾的空格符ymin=objecto.split(',')[1]  # ymin = '478)'ymin=ymin.split(')')[0]   # ymin = '478'  可能存在空格ymin=ymin.strip()    # strip函数去掉字符串开头结尾的空格符xmax=objecto.split(',')[2]  # xmax同理xmax=xmax.split('(')[1]xmax=xmax.strip()ymax=objecto.split(',')[3]   # ymax同理ymax=ymax.split(')')[0]ymax=ymax.strip()name=objecto.split(',')[4]  # 与上 同理name=name.strip()if name=="1 " or name=="1":  # 将数字信息转换成label字符串信息name='airplane'elif name=="2 "or name=="2":name='ship'elif name== "3 "or name=="3":name='storage tank'elif name=="4 "or name=="4":name='baseball diamond'elif name=="5 "or name=="5":name='tennis court'elif name=="6 "or name=="6":name='basketball court'elif name=="7 "or name=="7":name='ground track field'elif name=="8 "or name=="8":name='harbor'elif name=="9 "or name=="9":name='bridge'elif name=="10 "or name=="10":name='vehicle'    else:print(path)            # print(xmin,ymin,xmax,ymax,name)xmins.append(xmin)ymins.append(ymin)xmaxs.append(xmax)ymaxs.append(ymax)names.append(name)filename_fill = str(int(filename)).zfill(6)   # 将xml的文件名填充为6位数,比如1.xml就改为000001.xmlfilename_jpg = filename_fill + ".jpg"    # 由于xml中存储的文件名为000001.jpg,所以还得对所有的NWPU数据集中的图片进行重命名print(filename_fill)dealpath = outpath + filename_fill +".xml"# 注意,经过重命名转换之后,图片都存放在E:/Remote Sensing/Data Set/VOCdevkit2007/VOC2007/JPEGImages/中imagepath = "D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/JPEGImages/" + filename_fill + ".jpg"with open(dealpath, 'w') as f:img=Image.open(imagepath) # 根据图片的地址打开图片并获取图片的宽 和 高width=img.size[0]height=img.size[1]# 将图片的宽和高以及其他和VOC数据集向对应的信息writexml(dealpath,filename_jpg,num,xmins,ymins,xmaxs,ymaxs,names, height, width)#  同时也得给negative image set文件夹下面的所有负样本图片生成xml标注negative_path = "D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/negative image set/"negative_images = os.listdir(negative_path)for file in negative_images:filename = file.split('.')[0]  # 获取文件名,不包括后缀名filename_fill = str(int(filename) + 650).zfill(6)   # 将xml的文件名填充为6位数。同时加上650,比如1.xml就改为00001.xmlfilename_jpg = filename_fill + '.jpg'   # 比如第一个负样本001.jpg的filename_jpg 为000651.jpg## 重命名为6位数print(filename_fill)## 生成不含目标的xml文件dealpath = outpath + filename_fill +".xml"# 注意,经过重命名转换之后,图片都存放在E:/Remote Sensing/Data Set/VOCdevkit2007/VOC2007/JPEGImages/中imagepath = "D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/JPEGImages/" + filename_fill + ".jpg"with open(dealpath, 'w') as f:img = Image.open(imagepath)width = img.size[0]height = img.size[1]# 将宽高和空的目标标注信息写入xml标注writexml(dealpath,filename_jpg,num = 0,xmins = [],ymins = [],xmaxs = [],ymaxs = [],names = [],width=width,height=height)# NWPU数据集中标注的五维信息 (x1,y1) denotes the top-left coordinate of the bounding box,
#  (x2,y2) denotes the right-bottom coordinate of the bounding box
# 所以 xmin = x1  ymin = y1,  xmax = x2, ymax = y2  同时要注意这里的相对坐标是以图片左上角为坐标原点计算的
# VOC数据集对于包围框标注的格式是bounding-box(包含左下角和右上角xy坐标# 将从txt读取的标注信息写入到xml文件中
def writexml(path,filename,num,xmins,ymins,xmaxs,ymaxs,names,height, width):# Nwpu-vhr-10 < 1000*600node_root=Element('annotation')node_folder=SubElement(node_root,'folder')node_folder.text="VOC2007"node_filename=SubElement(node_root,'filename')node_filename.text="%s" % filenamenode_size=SubElement(node_root,"size")node_width = SubElement(node_size, 'width')node_width.text = '%s' % widthnode_height = SubElement(node_size, 'height')node_height.text = '%s' % heightnode_depth = SubElement(node_size, 'depth')node_depth.text = '3'for i in range(num):node_object = SubElement(node_root, 'object')node_name = SubElement(node_object, 'name')node_name.text = '%s' % names[i]node_name = SubElement(node_object, 'pose')node_name.text = '%s' % "unspecified"node_name = SubElement(node_object, 'truncated')node_name.text = '%s' % "0"node_difficult = SubElement(node_object, 'difficult')node_difficult.text = '0'node_bndbox = SubElement(node_object, 'bndbox')node_xmin = SubElement(node_bndbox, 'xmin')node_xmin.text = '%s'% xmins[i]node_ymin = SubElement(node_bndbox, 'ymin')node_ymin.text = '%s' % ymins[i]node_xmax = SubElement(node_bndbox, 'xmax')node_xmax.text = '%s' % xmaxs[i]node_ymax = SubElement(node_bndbox, 'ymax')node_ymax.text = '%s' % ymaxs[i]xml = tostring(node_root, pretty_print=True)  dom = parseString(xml)with open(path, 'wb') as f:f.write(xml)returnif __name__ == "__main__":# path指定的是标注txt文件所在的路径path = "D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/ground truth"deal(path)print("done!")

特别注意以下几点内容
       1.代码里只需要修改outpath 、negative_path、imagepath、path这四个变量的路径值(也就是代码里面所有和路径相关的变量,都需要改成自己的实际路径) ,其他不需要修改。修改后Annotations文件夹的部分内容如下:

最后我们来处理ImageSets文件夹,我们对NWPU VHR-10数据集进行划分,划分为train、val、trainval、test四个文件(其中train代表训练集数据信息,val代表验证集数据信息,trainval代表训练和验证集合并的数据信息,test为测试集数据的信息)。需要注意到trainval、test组成了整个数据集的信息,仔细分清楚各个之间的关系。我们给出划分数据集信息的代码,划分后的数据集信息存放在D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/ImageSets/Main文件夹里面(注意:这里的路径同样是自定义路径,不再做过多解释),具体的代码如下:

import os
import randomtrainval_percent = 0.8  # 表示训练集和验证集(交叉验证集)所占总图片的比例
train_percent = 0.75  # 训练集所占交叉验证集的比例
xmlfilepath = 'D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/Annotations'
txtsavepath = 'D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/ImageSets/Main'
total_xml = os.listdir(xmlfilepath)num = 650  # 有目标的图片数
list = range(num)
tv = int(num * trainval_percent)  # xml文件中的交叉验证集数
tr = int(tv * train_percent)  # xml文件中的训练集数,注意,我们在前面定义的是训练集占交叉验证集的比例
trainval = random.sample(list, tv)
train = random.sample(trainval, tr)ftrainval = open('D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/ImageSets/Main/trainval.txt', 'w')
ftest = open('D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/ImageSets/Main/test.txt', 'w')
ftrain = open('D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/ImageSets/Main/train.txt', 'w')
fval = open('D:/deeplearning-by-liaohuan/object-detection/datasets/NWPU-VHR-10 dataset/nwpu-10/voc-nwpu-10/ImageSets/Main/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)for i in range(150):num = str(651 + i).zfill(6) + '\n'ftest.write(num)ftrainval.close()
ftrain.close()
fval.close()
ftest.close()print("done!")

特别注意以下几点内容
       1.代码里修改的变量为xmlfilepath 、txtsavepath 、ftrainval、ftest、ftrain和fval.
       2.由于NWPU-VHR-10 dataset中只有positive image set文件夹中的650张图片包含目标的标注信息,所以训练集train及验证集val只能在从这650张图片中划分,negative image set文件夹中的150张图片不包含目标的标注信息,划分在测试集test中.
       3.代码中的trainval_percent 代表trainval.txt所占总数据集的比例,train_percent 代表在train.txt所占trainval.txt数据集(这里的总数据集是650张图片,不包括不标注的150张图片)的比例,千万别搞混了,这里的比例自己也可以进行修改!这样我们就成功的将西工大数据集转为VOC格式的数据集了。最后,ImageSets的Main文件夹的内容为:

3. yolov3 spp 训练NWPU-VHR-10 dataset

3.1 源码下载及其相关准备文件

前提说明:以下操作都在本地环境OK的情况下进行的,如果没有配置好环境,请根据下面源码链接里环境配置一栏一一配置完成
       首先下载yolov3 spp 源码(yolov3 spp源码链接),之后准备新建一个pascal_voc_classes.json放在源码的data文件夹下(注意:如果源码里面本来存在pascal_voc_classes.json,那么修改其内容如下即可),因为我们这里使用的NWPU-VHR-10 dataset数据集,所以种类一共有10类,其json文件的代码如下所示:

{"airplane": 1,"ship": 2,"storage tank": 3,"baseball diamond": 4,"tennis court": 5,"basketball court": 6,"ground track field": 7,"harbor": 8,"bridge": 9,"vehicle": 10
}

其json文件在源代码的目录摆放位置如下图所示(data文件夹里面其他文件暂时先别管,后面会生成):

3.2 VOC格式数据集转换为yolo格式

使用源码根目录当中trans_voc2yolo.py脚本进行转换,并在源码下的data文件夹下生成my_data_label.names标签文件.执行脚本前,需要根据自己的路径修改trans_voc2yolo.py中的一些参数:(特别注意:这里的voc_root、voc_version正好对应于我们在上一部分处理得到的VOC格式的西工大数据集的最外面两层的文件夹名字,其他的路径按照以下代码照搬即可

voc_root = "nwpu-10"
voc_version = "voc-nwpu-10"# 转换的训练集以及验证集对应txt文件
train_txt = "train.txt"
val_txt = "val.txt"# 转换后的文件保存目录
save_file_root = "./my_yolo_dataset"# label标签对应json文件
label_json_path = './data/pascal_voc_classes.json'

转换之后生成my_data_label.names标签文件、以及train、val文件夹,其中文件夹内的labels为图片的标签,而image为图片的路径信息,生成的内容如下图所示:

然后,我们先来处理一下源码cfg文件夹下的yolov3-spp.cfg文件,这里我们需要修改两个参数,分别是如下代码的filters、classes,特别注意:我们的种类是10,所以classes为10,filters的计算公式为(classes + 5)x3,所以filters为45.

[convolutional]
size=1
stride=1
pad=1
filters=45
activation=linear[yolo]
mask = 6,7,8
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=10
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1

之后使用源码根目录下的calculate_dataset.py脚本生成my_train_data.txt文件、my_val_data.txt文件以及my_data.data文件,并生成新的my_yolov3.cfg文件,执行脚本前,需要修改以下参数:

train_annotation_dir = "./my_yolo_dataset/train/labels"
val_annotation_dir = "./my_yolo_dataset/val/labels"
classes_label = "./data/my_data_label.names"
cfg_path = "./cfg/yolov3-spp.cfg"

特别注意:这里的train_annotation_dir、val_annotation_dir、classes_label、cfg_path 在之前的操作中都已经生成,只需要根据实际路径进行相关修改(如果一直跟着我的操作,则不需要修改路径)

运行calculate_dataset.py脚本之后,会在data文件夹下生成my_train_data.txt文件、my_val_data.txt文件以及my_data.data文件,并在cfg文件夹下生成新的my_yolov3.cfg文件,如下图所示:

特别注意:至此,我们已经将NWPU-VHR-10 dataset的VOC格式数据集转换成了yolo格式的数据集.

4. yolov3 spp 项目参数解析、如何获取best.pt以及定位到对应的epoch

首先,我们在上面yolov3 spp源码链接预训练权重下载地址一栏,下载相应的权重,博主使用的是yolov3-spp-ultralytics-512.pt权重,并存放在根目录下的weight文件夹下,如下图所示:

4.1 yolov3 spp 项目部分参数解析

为了成功启动项目,首先我们在项目中定位到train.py文件,找到如下代码所在位置,将nw设置为0,因为博主是在windows下跑项目,所以需要设置为0:

 nw = 0  # min([os.cpu_count(), batch_size if batch_size > 1 else 0, 8])  # number of workers windows默认设置为0

继续在train.py文件的关注以下代码:

if __name__ == '__main__':parser = argparse.ArgumentParser()parser.add_argument('--epochs', type=int, default=200)parser.add_argument('--batch-size', type=int, default=8)parser.add_argument('--cfg', type=str, default='cfg/my_yolov3.cfg', help="*.cfg path")parser.add_argument('--data', type=str, default='data/my_data.data', help='*.data path')parser.add_argument('--hyp', type=str, default='cfg/hyp.yaml', help='hyperparameters path')parser.add_argument('--multi-scale', type=bool, default=True,help='adjust (67%% - 150%%) img_size every 10 batches')parser.add_argument('--img-size', type=int, default=512, help='test size')parser.add_argument('--rect', action='store_true', help='rectangular training')parser.add_argument('--savebest', type=bool, default=True, help='only save best checkpoint')parser.add_argument('--notest', action='store_true', help='only test final epoch')parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')parser.add_argument('--weights', type=str, default='weights/yolov3-spp-ultralytics-512.pt',help='initial weights path')parser.add_argument('--name', default='', help='renames results.txt to results_name.txt if supplied')parser.add_argument('--device', default='cuda:0', help='device id (i.e. 0 or 0,1 or cpu)')parser.add_argument('--single-cls', action='store_true', help='train as single-class dataset')parser.add_argument('--freeze-layers', type=bool, default=False, help='Freeze non-output layers')parser.add_argument('--seed', type=int, default=42,help='Random seed.')# 是否使用混合精度训练(需要GPU支持混合精度)parser.add_argument("--amp", default=False, help="Use torch.cuda.amp for mixed precision training")opt = parser.parse_args()# 检查文件是否存在opt.cfg = check_file(opt.cfg)opt.data = check_file(opt.data)opt.hyp = check_file(opt.hyp)print(opt)with open(opt.hyp) as f:hyp = yaml.load(f, Loader=yaml.FullLoader)print('Start Tensorboard with "tensorboard --logdir=runs", view at http://localhost:6006/')tb_writer = SummaryWriter(comment=opt.name)seed_torch(opt.seed)train(hyp)

特别注意以下几点:
       1.epoch为项目训练的次数,batch_size为批量数,cfg指定到我们生成的my_yolov3.cfg(自己数据集生成的配置文件)路径,其他的都是类似.

2.代码中的–seed是我后来添加进去的,这是为了能够复现实验效果而编写的(注意,即使固定了随机种子,两次同样的实验也不保证实验数据完全一样,还有很大因素会影响最终的实验结果,只能说尽可能减少两次相同实验的数据误差),建议加上,其在seed_torch(opt.seed)中调用,seed_torch的函数也申明在train.py中(seed的具体取值可以自定义),代码如下所示:

def seed_torch(seed=42):seed = int(seed)random.seed(seed)os.environ['PYTHONHASHSEED'] = str(seed)np.random.seed(seed)torch.manual_seed(seed)torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed)torch.backends.cudnn.deterministic = Truetorch.backends.cudnn.benchmark = Falsetorch.backends.cudnn.enabled = False

3.特别注意到–savebest参数,我这里设置的是true,是因为我的需求只要最好生成的权重文件best.pt;如果想要每一个epoch的权重文件,设置为False即可

4.2 如何获取best.pt以及定位到对应的epoch

训练完成之后,会生成一个best.pt存放在weight文件夹下,可yolov3 spp 项目本身不会告诉这个best.pt对应于哪一个epoch,因为我的需求是寻找到best.pt所对应epoch的map。我们在train.py文件夹中找到了best.pt即为map(0.5-0.9-all)最大一个所对应的epoch的权重,如下所示:

       仔细的发现,在训练完毕之后,会生成存放每一个epoch控制台输出的信息在根目录下的resultxxxx.txt文件中(xxxx中间代表的是数字,每个人或许都不相同),我们利用这个文件导入到excel表格中,找到第二列即为map(0.5-0.9-all)的值,这样再通过excel表格公式就可以计算出这一列最大的值所对应的epoch,从而获取到对应的map等相关数据。

5. 本篇小结

本篇博客主要分析了从NWPU-VHR-10 dataset格式转换为VOC,再次转换为yolo格式,以及在模型配置、模型参数解析方法的内容,通过仔细一步步的实验,完成了相关实验要求。

之所以比较啰嗦、详细的写实验文章,最重要的是记录实验的所思所想。而且对于本人基础比较差,网上的一些博客跳跃比较大,不太适合我,所以本人就详细、一步步的记录和分析实验的心路历程,希望能够让大家和自己能顺心的阅读。如在复现本文博客中有任何问题,请在评论区进行交流,这样大家就会有更多的收获,博主也会及时的进行交流。最后文末附上本人训练好的权重文件,供大家以需要时使用

本人训练好的权重文件best.pt(提取密码:1234)

【目标检测实验系列】使用yolov3 spp训练西工大遥感数据集NWPU VHR-10(包括如何将NWPU VHR-10转为VOC格式和yolov3 spp实验调试的详细步骤,且附上训练完的权重文件)相关推荐

  1. 目标检测方法系列:R-CNN, SPP, Fast R-CNN, Faster R-CNN, YOLO, SSD

    本文转载自: http://www.cnblogs.com/lillylin/p/6207119.html 目标检测方法系列--R-CNN, SPP, Fast R-CNN, Faster R-CNN ...

  2. anchor free 目标检测_《目标检测》系列之二:目标检测中的Anchor机制回顾

    前段时间,YOLOv4&v5大火,很多人忽视了yolov5在anchor上的一些细节变化,因此,本文从Faster RCNN着手,逐步分析SSD.YOLOv4&v5的anchor机制. ...

  3. 目标检测YOLO系列------YOLO简介

    目标检测YOLO系列------YOLO简介 1.为什么会出现YOLO算法 2.YOLO算法会逐渐成为目标检测的主流吗     YOLO以及各种变体已经广泛应用于目标检测算法所涉及到的方方面面,为了梳 ...

  4. 目标检测R-CNN系列简要总结(RCNN, FastRCNN, FasterRCNN)

    R-CNN: Region with CNN feature,是一个双阶段目标检测算法系列. 内容基于 b站霹雳吧啦Wz 博主,讲的很好,这里只是做简要总结. R-CNN: 只有Feature ext ...

  5. Ubuntu安装Blender并创建桌面快捷方式的详细步骤(基于官方下载.tar.xz文件)

    Ubuntu安装Blender并创建桌面快捷方式的详细步骤(基于官方下载.tar.xz文件) 1. 下载Blender 从blender官网下载.tar.xz安装文件,下载网址为:https://ww ...

  6. 目标检测方法系列——R-CNN, SPP, Fast R-CNN, Faster R-CNN, YOLO, SSD

    目录 相关背景 从传统方法到R-CNN 从R-CNN到SPP Fast R-CNN Faster R-CNN YOLO SSD 总结 参考文献 推荐链接 相关背景 14年以来的目标检测方法(以R-CN ...

  7. 目标检测 YOLO系列算法

    文章目录 1. YOLO算法 1.1 Yolo算法思想 1.2 Yolo的网络结构 1.2.1 网络输入 1.2.2 网络输出 1.7X7网格 2x30维向量 1.3 Yolo模型的训练 1.3.1训 ...

  8. 目标检测yolo系列

    出自科技猛兽知乎专栏,地址:科技猛兽目标检测专栏 前言 本文目的是用尽量浅显易懂的语言让零基础小白能够理解什么是YOLO系列模型,以及他们的设计思想和改进思路分别是什么.我不会把YOLO的论文给你用软 ...

  9. 目标检测 YOLO 系列模型

    前言 YOLO (You Only Look Once) 系列模型追求实时目标检测,因此会在一定程度上牺牲精度,以实现更高的检测速度. 如果你对这篇文章感兴趣,可以点击「[访客必读 - 指引页]一文囊 ...

最新文章

  1. QQ采用什么传输协议?
  2. DVWA--SQL注入
  3. 如何查找UI5应用对应在ABAP Netweaver服务器上的BSP应用名称
  4. html js 浏览器语言,js 判断浏览器语言的方法
  5. 1070. 结绳(25)
  6. Milking Time【动态规划-dp】
  7. 信息学奥赛一本通(1122:计算鞍点)
  8. 宁德时代:8-12 万元区间车型终极解决方案是巧克力换电
  9. python入门神器 知乎_如何处理 Python 入门难以进步的现象?
  10. python 字典默认会引用 除非深拷贝
  11. Qone 自动删除说说脚本
  12. [置顶]       Web开发百宝箱——提升网站档次的时尚 jQuery 图片滚动插件
  13. python123随机密码生成答案_###随机密码生成###python123
  14. 关于信号发生器的功能和参数介绍(二)
  15. 魔术方法、5个类的魔术属性和单态
  16. [开源]爱发布类似fir.im和蒲公英的App发布平台
  17. 案例2:丙类仓库建筑防火案例分析
  18. 【面试专栏】第三篇:Java基础:集合篇-List、Queue
  19. Navicat远程连接Oracle数据库
  20. Weisfeiler-Lehman(WL)算法

热门文章

  1. 键盘各种按键对应的ASII码
  2. CSS hover改变背景图片过渡动画生硬
  3. 开放云将使业务焕然一新
  4. 脱口而出的 “ 感谢的语言 ”
  5. Matlab之real和imag函数
  6. 【抓包】【Mac Charles】局域网无法抓包 手机热点来解决
  7. mysql 1045 远程_启用远程mysql连接:错误1045(28000):拒绝用户访问
  8. [企业信息化大家学系列]制造业税务成本
  9. 钒酸钠的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  10. 微信群发消息的三种操作,原来多群群发消息可以这样做