YOLO2 (2) 测试自己的数据

时间:2023-12-11 22:06:08

Windos10 linux同样过程

现有问题:

本文过程在linux下类似,可以正常通过。windons下,运行python脚本出现问题,无法正常输出0001.txt(标定文件),所以只能使用linux生成标定文件和路径文件txt,然后复制到windons下使用。

待解决问题:

重写训练部分代码,使得windons程序直接读取原始图像和标记文件,其余文件自动生成,然后开始训练、

1 准备数据

输入原始数据--yolo2训练----输出权重文件

这里用100张做样例:

原始数据

  1. 原始图像0001.jpg   - 0100.jpg                                                                       10张
  2. 描述图像中目标信息的0001.txt  - 0100.txt                                                    10个
  3. 存储每个训练图像绝对完整路径的train.txt                                                   1个
  4. 存储每个测试图像绝对完整路径   var.txt                                                      1个

问题1 无法直接得到 原始数据 2.描述图像中目标信息的txt,采间接的办法

  1. 使用标图软件得到描述图像信息的0001.xml                                  每个图象对应一张
  2. 0001.xml 通过python脚本转换 0001.txt

问题2 无法直接得到3,4完整路径,间接先获取图片名,然后加上路径名

  1. 获取 训练图像的名字到一个 train.txt
  2. 将这个txt转换成完整路径
  3. 获取 测试图像的名字到一个var.txt
  4. 将这个txt转换成完整路径

1.1 原始图像

首先准备好自己的数据集,最好固定格式,此处为例,采用jpg格式的图像,在名字上最好使用像VOC一样类似000001.jpg、000002.jpg这样

YOLO2 (2) 测试自己的数据

1.2 xml文件  描述图像中要识别的目标信息

每一个xml对应一张图像,并且每个xml中存放的是标记的各个目标的位置和类别信息,命名通常与对应的原始图像一样

YOLO2 (2) 测试自己的数据

因为做的是目标检测,所以接下来需要标记原始图像中的目标区域。相关方法和工具有很多,这里需用labelImg,相关用法也有说明,基本就是框住目标区域然后双击类别,标记完整张图像后点击保存即可。操作界面如下:

YOLO2 (2) 测试自己的数据

通常save之后会将标记的信息保存在xml文件,其名字通常与对应的原始图像一样。

其中每个xml文件是这样的画风

<?xml version="1.0" ?>
<annotation>
<folder>JPEGImages</folder>
<filename>00000</filename>
<path>/home/kinglch/VOC2007/JPEGImages/00000.jpg</path>
<source>
<database>Unknown</database>
</source>
<size>
<width>704</width>
<height>576</height>
<depth>3</depth>
</size>
<segmented>0</segmented>
<object>
<name>person</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>73</xmin>
<ymin>139</ymin>
<xmax>142</xmax>
<ymax>247</ymax>
</bndbox>
</object>
<object>
<name>person</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>180</xmin>
<ymin>65</ymin>
<xmax>209</xmax>
<ymax>151</ymax>
</bndbox>
</object>

  

1.3 xml-txt文件  描述图像中要识别的目标信息

生成的xml文件不是yolo2读取的格式,所以需要转换为和图像名称一样的txt。

转换后的txt格式:<object-class> <x> <y> <width> <height>

  • 0 15 4 25 25           目标为第一类  起始位置 (15, 4)   长 25 宽 25
  • 0 11 36 25 25         目标为第一类  起始位置 (11, 36)   长 25 宽 25
  • YOLO2 (2) 测试自己的数据

该部分由1.4中的creat_list.py脚本自动完成。

1.4获取图像的路径,以便YOLO程序能够找到图片

图像分为两类,一类充当测试数据 剩下的充当训练数据。所以需要分别建立txt保存他们的路径地址。这里使用python脚本来自动生成路径。

生成过程分两步,首先获取图像的名字 

1.4.1 图片名 train.txt   只存每个训练的图象的名字  

1.4.2 图片名 val.txt     只存每个验证的图像的名字

在生成infrared_train.txt与infrared_val.txt这两个文件时,会分别用到这两个文档。文档里包含了用于训练/验证的图片的名称,里面的数据组成很简单,每行都是一个图片的名称,并不包含图片的后缀(.jpg),比如文档中:

  • 第一行是: 0000
  • 第二行是: 0001

该部分工作由生成脚本:creat_list.py:完成

自己需要改三个路径:

  • 图片原始地址
  • 生成用于保存训练集图像名字train.txt的路径
  • 生成用于保存测试集图像名字val.txt的路径
#这个小脚本是用来打开图片文件所在文件夹,把前900个用于训练的图片的名称保存在tain.txt,后103个用于验证的图片保存在val.txt
import os
from os import listdir, getcwd
from os.path import join
if __name__ == '__main__':
source_folder='/home/yolo_v2_tinydarknet/darknet/infrared/image/dout/'#地址是所有图片的保存地点
dest='/home/yolo_v2_tinydarknet/darknet/infrared/train.txt' #保存train.txt的地址
dest2='/home/yolo_v2_tinydarknet/darknet/infrared/val.txt' #保存val.txt的地址
file_list=os.listdir(source_folder) #赋值图片所在文件夹的文件列表
train_file=open(dest,'a') #打开文件
val_file=open(dest2,'a') #打开文件
for file_obj in file_list: #访问文件列表中的每一个文件
file_path=os.path.join(source_folder,file_obj)
#file_path保存每一个文件的完整路径
file_name,file_extend=os.path.splitext(file_obj)
#file_name 保存文件的名字,file_extend保存文件扩展名
file_num=int(file_name)
#把每一个文件命str转换为 数字 int型 每一文件名字都是由四位数字组成的 如 0201 代表 201 高位补零
if(file_num<900): #保留900个文件用于训练
#print file_num
train_file.write(file_name+'\n') #用于训练前900个的图片路径保存在train.txt里面,结尾加回车换行
else :
val_file.write(file_name+'\n') #其余的文件保存在val.txt里面
train_file.close()#关闭文件
val_file.close()

 然后通过得到的名字生成完整路径 

3.3  infrared_train.txt    存放训练的图像的地址

3.4 infrared_val.txt      存放测试的图像的地址

文档里包含了所有用于训练/验证的图片的完整路径,每一行都是一个图片的完整路径,例如 
第一行是: /home/yolo_v2_tinydarknet/darknet/infrared/image/dout/0000.jpg 
第二行是 :/home/yolo_v2_tinydarknet/darknet/infrared/image/dout/0001.jpg

该部分由以下脚本完成

需要分两次执行脚本。两次不一样的地方标红

第一次 生成训练集的完整路径

  • 1修改图像生成的xml文件所在地
  • in_file = open('/home/yolo_v2_tinydarknet/darknet/infrared/labels/dout_original/%s.xml'%(image_id))#与图片对应的xml文件所在的地址
  • 2修改转化后生成的txt的保存路径
  • out_file = open('/home/yolo_v2_tinydarknet/darknet/infrared/labels/%s.txt'%(image_id),'w') #与此xml对应的转换后的txt,这个txt的保存完整路径
  • 3打开训练集的两行代码注释,并将测试集的两行代码注释加上
  • image_ids = open('/home/yolo_v2_tinydarknet/darknet/infrared/train.txt').read().strip().split()  #如果是训练集数据打开这一行,注释下一行
  • list_file = open('infrared_train.txt', 'w')     #把结果写入到indrared_train.txt文件中,如果是训练集数据打开这一行,注释下一行
  • 4修改图片路径
  • list_file.write('/home/yolo_v2_tinydarknet/darknet/infrared/image/dout/%s.jpg\n'%(image_id))  #把每一用于训练或验证的图片的完整的路径写入到infrared_train.txt中  这个文件会被voc.data yolo.c调用

第二次 生成测试集的完整路径

  • 1修改图像生成的xml文件所在地
  • in_file = open('/home/yolo_v2_tinydarknet/darknet/infrared/labels/dout_original/%s.xml'%(image_id))#与图片对应的xml文件所在的地址
  • 2修改转化后生成的txt的保存路径
  • out_file = open('/home/yolo_v2_tinydarknet/darknet/infrared/labels/%s.txt'%(image_id),'w') #与此xml对应的转换后的txt,这个txt的保存完整路径
  • 3打开测试集的两行代码注释,并将训练集的两行代码注释加上
  • image_ids = open('/home/yolo_v2_tinydarknet/darknet/infrared/train.txt').read().strip().split()  #如果是测试数据打开这一行,注释下一行
  • list_file = open('infrared_train.txt', 'w')     #把结果写入到indrared_train.txt文件中,如果测试集数据打开这一行,注释下一行
  • 4修改图片路径
  • list_file.write('/home/yolo_v2_tinydarknet/darknet/infrared/image/dout/%s.jpg\n'%(image_id))  #把每一用于训练或验证的图片的完整的路径写入到infrared_train.txt中  这个文件会被voc.data yolo.c调用

  

#此脚本修改自voc_label.py。修改的原因是:我的训练集跟voc有些不同。
#由于数据集中包括用于训练的数据和用于验证的数据,所以此脚本可能需要分别对这两种数据各运行一次,对两种数据只需要简单地注释掉相应语句即可
#这个脚本需要train.txt ,这个文件是我用脚本creat_list.py生成的,保存了用于训练的图片的名字id,保存了用于训练的图片的名字
#这个脚本需要val.txt文件,这个文件是我用脚本creat_list.py生成的,保存了用于验证的图片的名字id,保存了用于验证的图片的名字
#这个脚本还需要xml格式的标签文件,我的训练集xml文件的格式与voc2007的类似,xml文件的名称与对应的用于训练的图片的名称相同
#这个脚本会生成 indrared_train.txt文件 ,用于保存每一用于训练的图片的完整的路径,随后会被voc.data yolo.c使用
#这个脚本会生成 indrared_val.txt文件 ,用于保存每一用于验证的图片的完整的路径,随后会被voc.data yolo.c使用
#这个脚本还会生成 txt格式的yolo可识别的标签文件,转换自每一个用于训练或验证的图片对应的xml文件,txt格式的文件名称与对应的xml文件名相同,但是内容不同,扩展名不同
#这个脚本 需要与图片对应的xml文件所在的地址,需要,转换后生成的txt的完整保存路径
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
#sets=[('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')] #按照自己的文件格式改的,不需要判断是那个voc数据包
classes = ["n00000001"]#因为我的数据集只有一个类别
def convert(size, box):#voc_label.py 自带的函数,没有修改
dw = 1./size[0]
dh = 1./size[1]
x = (box[0] + box[1])/2.0
y = (box[2] + box[3])/2.0
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 convert_annotation(image_id):
#in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
in_file = open('/home/yolo_v2_tinydarknet/darknet/infrared/labels/dout_original/%s.xml'%(image_id))#与图片对应的xml文件所在的地址
out_file = open('/home/yolo_v2_tinydarknet/darknet/infrared/labels/%s.txt'%(image_id),'w') #与此xml对应的转换后的txt,这个txt的保存完整路径
tree=ET.parse(in_file)
root = tree.getroot()
size = root.find('size') #访问size标签的数据
w = int(size.find('width').text)#读取size标签中宽度的数据
h = int(size.find('height').text)#读取size标签中高度的数据 for obj in root.iter('object'):
# difficult = obj.find('difficult').text #由于自己的文件里面没有diffcult这一个标签,所以就屏蔽之
cls = obj.find('name').text
if cls not in classes :#or int(difficult) == 1:
continue
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox') #访问boundbox标签的数据并进行处理,都按yolo自带的代码来,没有改动
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
bb = convert((w,h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n') #image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split() #之前代码是按照sets里面的字符来访问保存有图片名字的train或者val的txt文件
image_ids = open('/home/yolo_v2_tinydarknet/darknet/infrared/train.txt').read().strip().split() #如果是训练集数据打开这一行,注释下一行
#image_ids = open('/home/yolo_v2_tinydarknet/darknet/infrared/val.txt').read().strip().split() #如果是验证数据集数据打开这一行,注释上一行
#list_file = open('%s_%s.txt'%(year, image_set), 'w')
list_file = open('infrared_train.txt', 'w') #把结果写入到indrared_train.txt文件中,如果是训练集数据打开这一行,注释下一行
#list_file = open('infrared_val.txt', 'w') #把结果写入到indrared_train.txt文件中,如果是验证数据集数据打开这一行,注释上一行
for image_id in image_ids:
#list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
list_file.write('/home/yolo_v2_tinydarknet/darknet/infrared/image/dout/%s.jpg\n'%(image_id)) #把每一用于训练或验证的图片的完整的路径写入到infrared_train.txt中 这个文件会被voc.data yolo.c调用
convert_annotation(image_id) #把图片的名称id传给函数,用于把此图片对应的xml中的数据转换成yolo要求的txt格式
list_file.close() #关闭文件

  

原始数据结果

经过以上步骤,我们现在得到以下数据:

  1. 原始照片                                                                                        100张      jpg
  2. 和原始照片名一样的,用于保存图像中要识别的目标信息的txt     100个      txt
  3. 用于参加训练的图片的路径地址 infrared_train.txt                           一个      txt
  4. 用于参加训练的图片的路径地址 infrared_val.txt                              一个     txt

2 修改工程配置文件

在工程生成的x64/data路径下

2.1新建 yolo-obj.cfg 文件,内容复制yolo-voc.2.0.cfg文件(x64路径下),但是修改:

  • 第一行
  • change line batch to batch=64
  • 第二行
  • change line subdivisions to subdivisions=8
  • YOLO2 (2) 测试自己的数据

  • 修改region层  classes 自己训练的类 这里是1类  只有car
  • YOLO2 (2) 测试自己的数据
  • 修改region上一层convolutional层中 filters= (classes+5)*5    这里  classes为一类   filters= (1+5)*5=30
  • YOLO2 (2) 测试自己的数据

2.2 创建obj.names  在文件夹build\darknet\x64\data\里,里面是你所分的类 这里为一类 car

YOLO2 (2) 测试自己的数据

如果很多类,例如voc.data 分了很多类数据

YOLO2 (2) 测试自己的数据

2.3 创建obj.data在 build\darknet\x64\data\路径下

  • 我们只有一类car 所以classes=1

YOLO2 (2) 测试自己的数据

  • train= 数据准备生成的 保存训练图片完整路径的 train.txt

YOLO2 (2) 测试自己的数据

YOLO2 (2) 测试自己的数据

  • valid=数据准备生成的 保存测试图片完整路径的 var.txt

YOLO2 (2) 测试自己的数据

YOLO2 (2) 测试自己的数据

  • backup = backup 存放的是 生成的权重文件路径 默认x64/backp下

2.4 将原始图片集存在build\darknet\x64\data\obj\

2.4 将数据处理得到的描述每个图像中 目标信息的txt文件 也放在build\darknet\x64\data\obj\ 下

YOLO2 (2) 测试自己的数据

每个txt内容

YOLO2 (2) 测试自己的数据

3 开始训练

3.1 训练需要用到一个文件

下载 pre-trained weights for the convolutional layers (76 MB):

http://pjreddie.com/media/files/darknet19_448.conv.23

放在build\darknet\x64下

3.2 运行训练命令  命令行进入build\darknet\x64下

darknet.exe detector train data/obj.data data/yolo-obj.cfg darknet19_448.conv.23

3.3生成结果在 build\darknet\x64\backup

每次迭代100次,保存下,取最后一个

YOLO2 (2) 测试自己的数据