SSD-tensorflow-2 制作自己的數據集


VOC2007數據集格式:

VOC2007詳細介紹在這里,提供給大家有興趣作了解。而制作自己的數據集只需用到前三個文件夾,所以請事先建好這三個文件夾放入同一文件夾內,同時ImageSets文件夾內包含Main文件夾

JPEGImages:用於存放訓練、測試的圖片(圖片格式最好為.jpg)
Annatations:用於存放.xml格式的文件,也就是圖片對應的標簽,每個.xml文件都對應於JPEGImages文件夾的一張圖片
ImageSets:內含Main文件夾,在…/ImageSets/Main文件夾下包含test.txt、train.txt、val.txt、trainval.txt四個文件,生成的方式第二步有詳細說明

第一步

下載圖片,存入JPEGImages文件夾——你可以直接從各種渠道下載得到所需要的圖片集,存入到JPEGImages文件夾下,命名格式統一為“00xxxx.jpg”,如下圖:

第二步

使用labelImg工具給圖片打標簽——這是最重要的一步。如果你的python已經pip install lxml下載了lxml

 

labelImg工具簡單的使用步驟就是:

打開單個文件,或者打開一個圖片文件夾
給目標物體建立box邊框
對box邊框內的物體貼上標簽
把一張圖片內所有目標物都打上各自標簽后,再保存生成.xml文件,注意存入Annatations文件夾,文件名也要與當前圖片保存一致
然后next下一張圖片繼續打標簽,直到所有圖片內物體都打上了標簽,最后exit

第三步

生成Main文件夾下的.txt文件——在主目錄下運行以下代碼既可生成test.txt、train.txt、val.txt、trainval.txt四個文件,請注意每一個path地址是否正確(其實這四個txt文件在后續並沒有什么用處)

 1 # -*- coding:utf-8 -*-
 2 # -*- author:zzZ_CMing  CSDN address:https://blog.csdn.net/zzZ_CMing
 3 # -*- 2018/07/18; 15:19
 4 # -*- python3.5
 5 import os  
 6 import random  
 7 
 8 trainval_percent = 0.7  
 9 train_percent = 0.8
10 xmlfilepath = 'Annotations'
11 txtsavepath = 'ImageSets/Main'  
12 total_xml = os.listdir(xmlfilepath)  
13 
14 num = len(total_xml)  
15 list = range(num)  
16 tv = int(num*trainval_percent)  
17 tr = int(tv*train_percent)  
18 trainval = random.sample(list,tv)  
19 train = random.sample(trainval,tr)  
20 
21 ftrainval = open(txtsavepath+'/trainval.txt', 'w')  
22 ftest = open(txtsavepath+'/test.txt', 'w')  
23 ftrain = open(txtsavepath+'/train.txt', 'w')  
24 fval = open(txtsavepath+'/val.txt', 'w')  
25 
26 for i in list:  
27     name = total_xml[i][:-4]+'\n'  
28     if i in trainval:  
29         ftrainval.write(name)  
30         if i in train:  
31             ftrain.write(name)  
32         else:  
33             fval.write(name)  
34     else:  
35         ftest.write(name)  
36 
37 ftrainval.close()  
38 ftrain.close()  
39 fval.close()  
40 ftest .close()
41 print('Well Done!!!')

運行完成,得到如下文件:可以打開看一看,內容就是各個圖片的索引,意味着哪些圖片用做訓練,哪些用做測試。

 

第四步

用.xml標簽,生成.tfrecord文件

說明:SSD框架所用到的標簽文件並不直接是.xml格式文件,而是.tfrecord文件

特別注意:要在主目錄提前建好tfrecords_文件夾,不然會報錯找不到目標文件夾

 

  1 # -*- coding:utf-8 -*-
  2 # -*- author:zzZ_CMing  CSDN address:https://blog.csdn.net/zzZ_CMing
  3 # -*- 2018/07/17; 13:18
  4 # -*- python3.5
  5 """
  6 特別注意: path地址是否正確、要在主目錄下提前創建“tfrecords_”文件夾
  7 """
  8 
  9 import os
 10 import sys
 11 import random
 12 import numpy as np
 13 import tensorflow as tf
 14 import xml.etree.ElementTree as ET  # 操作xml文件
 15 
 16 # 我的標簽定義只有兩類,要根據自己的圖片而定
 17 VOC_LABELS = {
 18     'none': (0, 'Background'),
 19     'aiaitie': (1, 'Product')
 20 }
 21 
 22 # 圖片和標簽存放的文件夾.
 23 DIRECTORY_ANNOTATIONS = 'Annotations/'
 24 DIRECTORY_IMAGES = 'JPEGImages/'
 25 
 26 # 隨機種子.
 27 RANDOM_SEED = 4242
 28 SAMPLES_PER_FILES = 3  # 每個.tfrecords文件包含幾個.xml樣本
 29 
 30 
 31 # 生成整數型,浮點型和字符串型的屬性
 32 def int64_feature(value):
 33     if not isinstance(value, list):
 34         value = [value]
 35     return tf.train.Feature(int64_list=tf.train.Int64List(value=value))
 36 
 37 def float_feature(value):
 38     if not isinstance(value, list):
 39         value = [value]
 40     return tf.train.Feature(float_list=tf.train.FloatList(value=value))
 41 
 42 def bytes_feature(value):
 43     if not isinstance(value, list):
 44         value = [value]
 45     return tf.train.Feature(bytes_list=tf.train.BytesList(value=value))
 46 
 47 # 圖片處理
 48 def _process_image(directory, name):
 49     # Read the image file.
 50     filename = directory + DIRECTORY_IMAGES + name + '.jpg'
 51     image_data = tf.gfile.FastGFile(filename, 'rb').read()
 52 
 53     # Read the XML annotation file.
 54     filename = os.path.join(directory, DIRECTORY_ANNOTATIONS, name + '.xml')
 55     tree = ET.parse(filename)
 56     root = tree.getroot()
 57 
 58     # Image shape.
 59     size = root.find('size')
 60     shape = [int(size.find('height').text),
 61              int(size.find('width').text),
 62              int(size.find('depth').text)]
 63     # Find annotations.
 64     bboxes = []
 65     labels = []
 66     labels_text = []
 67     difficult = []
 68     truncated = []
 69     for obj in root.findall('object'):
 70         label = obj.find('name').text
 71         labels.append(int(VOC_LABELS[label][0]))
 72         labels_text.append(label.encode('ascii'))  # 變為ascii格式
 73 
 74         if obj.find('difficult'):
 75             difficult.append(int(obj.find('difficult').text))
 76         else:
 77             difficult.append(0)
 78         if obj.find('truncated'):
 79             truncated.append(int(obj.find('truncated').text))
 80         else:
 81             truncated.append(0)
 82 
 83         bbox = obj.find('bndbox')
 84         a = float(bbox.find('ymin').text) / shape[0]
 85         b = float(bbox.find('xmin').text) / shape[1]
 86         a1 = float(bbox.find('ymax').text) / shape[0]
 87         b1 = float(bbox.find('xmax').text) / shape[1]
 88         a_e = a1 - a
 89         b_e = b1 - b
 90         if abs(a_e) < 1 and abs(b_e) < 1:
 91             bboxes.append((a, b, a1, b1))
 92 
 93     return image_data, shape, bboxes, labels, labels_text, difficult, truncated
 94 
 95 # 轉化樣例
 96 def _convert_to_example(image_data, labels, labels_text, bboxes, shape,
 97                         difficult, truncated):
 98     xmin = []
 99     ymin = []
100     xmax = []
101     ymax = []
102     for b in bboxes:
103         assert len(b) == 4
104         # pylint: disable=expression-not-assigned
105         [l.append(point) for l, point in zip([ymin, xmin, ymax, xmax], b)]
106         # pylint: enable=expression-not-assigned
107 
108     image_format = b'JPEG'
109     example = tf.train.Example(features=tf.train.Features(feature={
110         'image/height': int64_feature(shape[0]),
111         'image/width': int64_feature(shape[1]),
112         'image/channels': int64_feature(shape[2]),
113         'image/shape': int64_feature(shape),
114         'image/object/bbox/xmin': float_feature(xmin),
115         'image/object/bbox/xmax': float_feature(xmax),
116         'image/object/bbox/ymin': float_feature(ymin),
117         'image/object/bbox/ymax': float_feature(ymax),
118         'image/object/bbox/label': int64_feature(labels),
119         'image/object/bbox/label_text': bytes_feature(labels_text),
120         'image/object/bbox/difficult': int64_feature(difficult),
121         'image/object/bbox/truncated': int64_feature(truncated),
122         'image/format': bytes_feature(image_format),
123         'image/encoded': bytes_feature(image_data)}))
124     return example
125 
126 # 增加到tfrecord
127 def _add_to_tfrecord(dataset_dir, name, tfrecord_writer):
128     image_data, shape, bboxes, labels, labels_text, difficult, truncated = \
129         _process_image(dataset_dir, name)
130     example = _convert_to_example(image_data, labels, labels_text,
131                                   bboxes, shape, difficult, truncated)
132     tfrecord_writer.write(example.SerializeToString())
133 
134 
135 # name為轉化文件的前綴
136 def _get_output_filename(output_dir, name, idx):
137     return '%s/%s_%03d.tfrecord' % (output_dir, name, idx)
138 
139 
140 def run(dataset_dir, output_dir, name='voc_train', shuffling=False):
141     if not tf.gfile.Exists(dataset_dir):
142         tf.gfile.MakeDirs(dataset_dir)
143 
144     path = os.path.join(dataset_dir, DIRECTORY_ANNOTATIONS)
145     filenames = sorted(os.listdir(path))  # 排序
146     if shuffling:
147         random.seed(RANDOM_SEED)
148         random.shuffle(filenames)
149         
150     i = 0
151     fidx = 0
152     while i < len(filenames):
153         # Open new TFRecord file.
154         tf_filename = _get_output_filename(output_dir, name, fidx)
155         with tf.python_io.TFRecordWriter(tf_filename) as tfrecord_writer:
156             j = 0
157             while i < len(filenames) and j < SAMPLES_PER_FILES:
158                 sys.stdout.write(' Converting image %d/%d \n' % (i + 1, len(filenames)))  # 終端打印,類似print
159                 sys.stdout.flush()  # 緩沖
160 
161                 filename = filenames[i]
162                 img_name = filename[:-4]
163                 _add_to_tfrecord(dataset_dir, img_name, tfrecord_writer)
164                 i += 1
165                 j += 1
166             fidx += 1
167 
168     print('\nFinished converting the Pascal VOC dataset!')
169 
170 
171 # 原數據集路徑,輸出路徑以及輸出文件名,要根據自己實際做改動
172 dataset_dir = "C:/Users/Admin/Desktop/"
173 output_dir = "./tfrecords_"
174 name = "voc_train"
175 
176 def main(_):
177     run(dataset_dir, output_dir, name)
178 
179 if __name__ == '__main__':
180     tf.app.run()

得到的.tfrecords文件如下:

 


免責聲明!

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



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