tensorflow yolov3訓練自己的數據集,詳細教程


這個教程是我在自己學習的過程中寫的,當作一個筆記,寫的比較詳細
在github上下載yolov3的tensorflow1.0版本:
https://github.com/YunYang1994/tensorflow-yolov3
在19年12月,發現網上訓練的教程大部分似乎已經過時了,因為作者對開源代碼進行了部分修改
其實在作者的readme上已經寫了訓練的方法,但是不是那么詳細,於是記錄下
由於本人水平有限,如果文章有不當之處還望評論區指出

一,制作訓練集

1,打標簽
訓練集需要實驗labelimg工具進行制作,這里的數據集格式采用的是voc格式:
labelimg下載地址
實驗labelimg打好標簽后會生成兩個文件夾:
Annotations —存放標記的圖片
JPEGImages —存放xml格式的標簽
這里不做多余的解釋
2,按照voc數據集格式建立文件夾

因為作者給的模型是訓練VOC數據集的模型,所以訓練我們自己的數據集的時候也需要改為VOC格式的,VOC格式解析:
第一步:首先了解VOC2007數據集的格式

  1. 1)JPEGImages文件夾

文件夾里包含了訓練圖片和測試圖片,混放在一起

  1. 2)Annatations文件夾

文件夾存放的是xml格式的標簽文件,每個xml文件都對應於JPEGImages文件夾的一張圖片

  1. 3)ImageSets文件夾

Action存放的是人的動作,我們暫時不用

Layout存放的人體部位的數據。我們暫時不用

Main存放的是圖像物體識別的數據,分為20類,當然我們自己制作就不一定了,如果你有精力,Main里面有test.txt , train.txt, val.txt ,trainval.txt.這四個文件我們后面會生成
train中存放的是訓練使用的數據,每一個class的train數據都有5717個。
val中存放的是驗證結果使用的數據,每一個class的val數據都有5823個。
trainval為訓練和驗證的圖片文件的文件名列表 。
Segmentation存放的是可用於分割的數據
如果你下載了VOC2007數據集,那么把它解壓,把各個文件夾里面的東西刪除,保留文件夾名字。如果沒下載,那么就仿照他的文件夾格式,按照這個目錄格式建立文件夾:
在這里插入圖片描述
然后分別把標記的圖片放入JPEGImages文件夾,標簽xml文件放入Annotations文件夾:
在這里插入圖片描述
在這里插入圖片描述
3,划分訓練集和測試集
訓練時要有測試集和訓練集,通過划分放在
VOCdevkit\VOC2008\ImageSets\Main
文件夾下,這里可以使用一段python代碼按照9:1進行隨機划分:
在VOC2008文件夾建立split.py

import os import random import sys if len(sys.argv) < 2: print("no directory specified, please input target directory") exit() root_path = sys.argv[1] xmlfilepath = root_path + '/Annotations' txtsavepath = root_path + '/ImageSets/Main' if not os.path.exists(root_path): print("cannot find such directory: " + root_path) exit() if not os.path.exists(txtsavepath): os.makedirs(txtsavepath) trainval_percent = 0.9 train_percent = 0.8 total_xml = os.listdir(xmlfilepath) 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("train size:", tr) ftrainval = open(txtsavepath + '/trainval.txt', 'w') ftest = open(txtsavepath + '/test.txt', 'w') ftrain = open(txtsavepath + '/train.txt', 'w') fval = open(txtsavepath + '/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() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

打開控制台,運行該python文件,后跟Annotation的目錄即可進行划分:

python .\split.py F:\dateset\hat_data\VOC\test\VOCdevkit\VOC2007 
  • 1

在這里插入圖片描述
train為訓練集,test為驗證集
4,根據划分結果制作訓練集
上面代碼已經實現了將數據集划分為訓練集和驗證集,但是tensorflow yolov3作者寫的模型要求的數據集格式為:

在這里插入圖片描述
所以我們需要寫一個小腳本,根據train.txt 和test.txt將數據集進行更改

import os from shutil import copyfile #根據tarin.txt和test.txt將數據集分為標准數據集 train_text_path = 'F:/dateset/hat_data/VOCdevkit/VOC2007/ImageSets/Main/train.txt' test_text_path = 'F:/dateset/hat_data/VOCdevkit/VOC2007/ImageSets/Main/test.txt' #圖片存放地址 image_path = 'F:/dateset/hat_data/VOCdevkit/VOC2007/JPEGImages' #xml文件存放地址 xml_path = 'F:/dateset/hat_data/VOCdevkit/VOC2007/Annotations' #輸出的目錄 outdir = 'F:/dateset/hat_data' #創建各級文件夾 test_xml_out = os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/Annotations') os.makedirs(test_xml_out) os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/ImageSets/Layout')) os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/ImageSets/Main')) os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/ImageSets/Segmentation')) test_img_out = os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/JPEGImages') os.makedirs(test_img_out) os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/SegmentationClass')) os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/SegmentationObject')) train_xml_out = os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/Annotations') os.makedirs(train_xml_out) os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/ImageSets/Layout')) os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/ImageSets/Main')) os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/ImageSets/Segmentation')) train_img_out = os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/JPEGImages') os.makedirs(train_img_out) os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/SegmentationClass')) os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/SegmentationObject')) with open(train_text_path) as f: lines = f.readlines() for i in lines: img_save_path = os.path.join(train_img_out,i.rstrip('\n')+'.jpg') xml_save_path = os.path.join(train_xml_out, i.rstrip('\n') + '.xml') copyfile(os.path.join(image_path,i.rstrip('\n')+'.jpg'),img_save_path) copyfile(os.path.join(xml_path, i.rstrip('\n') + '.xml'), xml_save_path) print(i) with open(test_text_path) as f: lines = f.readlines() for i in lines: img_save_path = os.path.join(test_img_out, i.rstrip('\n') + '.jpg') xml_save_path = os.path.join(test_xml_out, i.rstrip('\n') + '.xml') copyfile(os.path.join(image_path, i.rstrip('\n') + '.jpg'), img_save_path) copyfile(os.path.join(xml_path, i.rstrip('\n') + '.xml'), xml_save_path) print(i) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

根據這個小腳本就可進行划分為規定的格式,如果數據集的量比較大,可能有點慢,當然你也可以進行手動划分,省略前面幾步操作,只要最終目錄結構滿足作者的格式就行
在這里插入圖片描述
5,分別在test和train下面運行split.py腳本

 python .\split.py F:\dateset\hat_data\VOC\train\VOCdevkit\VOC2007 
  • 1
 python .\split.py F:\dateset\hat_data\VOC\test\VOCdevkit\VOC2007 
  • 1

二,制作標准數據集txt文件

作者在github上聲明,訓練需要兩個文件,如下所示:

dataset.txt:

xxx/xxx.jpg 18.19,6.32,424.13,421.83,20 323.86,2.65,640.0,421.94,20 xxx/xxx.jpg 48,240,195,371,11 8,12,352,498,14 image_path x_min, y_min, x_max, y_max, class_id x_min, y_min ,..., class_id make sure that x_max < width and y_max < height 
  • 1
  • 2
  • 3
  • 4

class.names:

person
bicycle
car
... toothbrush 
  • 1
  • 2
  • 3
  • 4
  • 5

1,生成dataset.txt
其實前幾步都是為這兩步做准備,通過目錄下的 scripts/voc_annotation.py就可以生成dataset.txt文件,但是需要改一些代碼參數:
只需更改 classes為自己的類別

classes = ['hat','person'] 
  • 1


default 更改為你自己的看注釋

    #default 更改為你自己數據集VOC的目錄 parser.add_argument("--data_path", default="F:/dateset/hat_data/VOC") #default 更改為voc_train.txt的存放的位置 parser.add_argument("--train_annotation", default="../data/dataset/voc_train.txt") parser.add_argument("--test_annotation", default="../data/dataset/voc_test.txt") flags = parser.parse_args() if os.path.exists(flags.train_annotation):os.remove(flags.train_annotation) if os.path.exists(flags.test_annotation):os.remove(flags.test_annotation) #更改訓練集和測試集的相對路徑 num1 = convert_voc_annotation(os.path.join(flags.data_path, 'train/VOCdevkit/VOC2007'), 'trainval', flags.train_annotation, False) num3 = convert_voc_annotation(os.path.join(flags.data_path, 'test/VOCdevkit/VOC2007'), 'trainval', flags.test_annotation, False) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

其他默認即可:
更改后的代碼:

import os import argparse import xml.etree.ElementTree as ET def convert_voc_annotation(data_path, data_type, anno_path, use_difficult_bbox=True): #更改為你自己的類別 classes = ['hat','person'] img_inds_file = os.path.join(data_path, 'ImageSets', 'Main', data_type + '.txt') with open(img_inds_file, 'r') as f: txt = f.readlines() image_inds = [line.strip() for line in txt] with open(anno_path, 'a') as f: for image_ind in image_inds: image_path = os.path.join(data_path, 'JPEGImages', image_ind + '.jpg') annotation = image_path label_path = os.path.join(data_path, 'Annotations', image_ind + '.xml') root = ET.parse(label_path).getroot() objects = root.findall('object') for obj in objects: difficult = obj.find('difficult').text.strip() if (not use_difficult_bbox) and(int(difficult) == 1): continue bbox = obj.find('bndbox') class_ind = classes.index(obj.find('name').text.lower().strip()) xmin = bbox.find('xmin').text.strip() xmax = bbox.find('xmax').text.strip() ymin = bbox.find('ymin').text.strip() ymax = bbox.find('ymax').text.strip() annotation += ' ' + ','.join([xmin, ymin, xmax, ymax, str(class_ind)]) print(annotation) f.write(annotation + "\n") return len(image_inds) if __name__ == '__main__': parser = argparse.ArgumentParser() #default 更改為你自己數據集VOC的目錄 parser.add_argument("--data_path", default="F:/dateset/hat_data/VOC") #default 更改為voc_train.txt的存放的位置 parser.add_argument("--train_annotation", default="../data/dataset/voc_train.txt") parser.add_argument("--test_annotation", default="../data/dataset/voc_test.txt") flags = parser.parse_args() if os.path.exists(flags.train_annotation):os.remove(flags.train_annotation) if os.path.exists(flags.test_annotation):os.remove(flags.test_annotation) #更改訓練集和測試集的相對路徑 num1 = convert_voc_annotation(os.path.join(flags.data_path, 'train/VOCdevkit/VOC2007'), 'trainval', flags.train_annotation, False) num3 = convert_voc_annotation(os.path.join(flags.data_path, 'test/VOCdevkit/VOC2007'), 'trainval', flags.test_annotation, False) print('=> The number of image for train is: %d\tThe number of image for test is:%d' %(num1 , num3)) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

更改后運行該python文件:
在這里插入圖片描述
在這里插入圖片描述
這就生成了dataset.txt
2,更改voc.names的類別
在這里插入圖片描述
修改為自己的類別:
在這里插入圖片描述
3,修改配置文件
編輯您的文件./core/config.py以進行一些必要的配置

_C.YOLO.CLASSES = "./data/classes/voc.names" __C.TRAIN.ANNOT_PATH = "./data/dataset/voc_train.txt" __C.TEST.ANNOT_PATH = "./data/dataset/voc_test.txt" 
  • 1
  • 2
  • 3

到這里已經配置完成,已經可以訓練了

三,訓練數據

1)從頭開始訓練:

$ python train.py $ tensorboard --logdir ./data 
  • 1
  • 2

在這里插入圖片描述
(2)從COCO配置訓練(推薦):

$ cd checkpoint
$ wget https://github.com/YunYang1994/tensorflow-yolov3/releases/download/v1.0/yolov3_coco.tar.gz $ tar -xvf yolov3_coco.tar.gz $ cd .. $ python convert_weight.py --train_from_coco $ python train.py 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.2評估VOC數據集

$ python evaluate.py $ cd mAP $ python main.py -na
原文:https://blog.csdn.net/qq_38441692/article/details/103652760


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM