赞
踩
前言:因为要依赖上一章SSD目标检测(1):图片+视频版物体定位(附源码)来训练预测自己的数据集,所以建立自己的数据集是一个复杂且避不开的步骤,以下给出了制作自己的数据集所要经过的简单步骤,而后也有更详细的说明奉上。
以下过程详细,如有不明请留言提醒,详细过程如下:
–-----------------------------------------------------------------------------—------------
本篇博客,我的数据集、代码存储在这里,有需要的同学自己下载。
–-----------------------------------------------------------------------------—------------
知己知彼,方百战不殆。想制作自己的数据集当然要先了解SSD使用的数据集VOC2007长啥样。VOC2007下载链接 ,密码是:m5io。(VOC2007完整下载有3个压缩包+1个PDF,上面链接里只包含其中一个压缩包VOCtrainval_06-Nov-2007)。打开压缩包就如下图:
VOC2007详细介绍在这里,提供给大家有兴趣作了解。而制作自己的数据集只需用到前三个文件夹,所以请事先建好这三个文件夹放入同一文件夹内,同时ImageSets
文件夹内包含Main
文件夹
–-----------------------------------------------------------------------------—------------
–-----------------------------------------------------------------------------—------------
第一步:下载图片,存入JPEGImages文件夹——你可以直接从各种渠道下载得到所需要的图片集,存入到JPEGImages文件夹下,命名格式统一为“00xxxx.jpg”,如下图:
–-----------------------------------------------------------------------------—--------**----
第二步:使用labelImg工具给图片打标签——这是最重要的一步。如果你的python已经pip install lxml
下载了lxml
,就可以直接在我网盘下载labelImg工具windows版使用,密码:gyf3。
通过以上网盘下载得到工具文件后,打开…/data/predefined_classes.txt文件,可以发现这里都是图片标签——把你将要用到的标签都事先存入在这里,注意标签不能有中文。每次使用都把.exe
、data
这两个文件拖到桌面上(如果直接在文件夹内运行.exe
会报错不能运行),打开labelImg.exe文件,运行界面如下:就可以开始给图片打标签了
labelImg工具简单的使用步骤就是:
–-----------------------------------------------------------------------------—--------**----
第三步:生成Main文件夹下的.txt文件——在主目录下运行以下代码既可生成test.txt、train.txt、val.txt、trainval.txt四个文件,请注意每一个path
地址是否正确(其实这四个txt文件在后续并没有什么用处)
# -*- coding:utf-8 -*- # -*- author:zzZ_CMing CSDN address:https://blog.csdn.net/zzZ_CMing # -*- 2018/07/18; 15:19 # -*- python3.5 import os import random trainval_percent = 0.7 train_percent = 0.8 xmlfilepath = 'Annotations/' txtsavepath = 'ImageSets/Main' 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) 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() print('Well Done!!!')
运行完成,得到如下文件:可以打开看一看,内容就是各个图片的索引,意味着哪些图片用做训练,哪些用做测试。
说明:SSD框架所用到的标签文件并不直接是.xml格式文件,而是.tfrecord文件,因为这一部分比较重要,代码先贴上——只为想研究如何生成.tfrecord文件的同学准备,想要了解 SSD目标检测(3):使用自己的数据集做识别(详细说明附源码),请继续点击,详细过程讲解+源码即刻奉上
# -*- coding:utf-8 -*- # -*- author:zzZ_CMing CSDN address:https://blog.csdn.net/zzZ_CMing # -*- 2018/07/17; 13:18 # -*- python3.5 """ 特别注意: 17行VOC_LABELS标签要修改,189行的path地址要正确 """ import os import sys import random import numpy as np import tensorflow as tf import xml.etree.ElementTree as ET # 我的标签定义只有手表这一类,所以下面的VOC_LABELS要根据自己的图片标签而定,第一组'none': (0, 'Background')是不能删除的; VOC_LABELS = { 'none': (0, 'Background'), 'watch': (1, 'watch') } # 图片和标签存放的文件夹. DIRECTORY_ANNOTATIONS = 'Annotations/' DIRECTORY_IMAGES = 'JPEGImages/' # 随机种子. RANDOM_SEED = 4242 SAMPLES_PER_FILES = 3 # 每个.tfrecords文件包含几个.xml样本 def int64_feature(value): """ 生成整数型,浮点型和字符串型的属性 """ if not isinstance(value, list): value = [value] return tf.train.Feature(int64_list=tf.train.Int64List(value=value)) def float_feature(value): if not isinstance(value, list): value = [value] return tf.train.Feature(float_list=tf.train.FloatList(value=value)) def bytes_feature(value): if not isinstance(value, list): value = [value] return tf.train.Feature(bytes_list=tf.train.BytesList(value=value)) def _process_image(directory, name): """ 图片处理 """ # Read the image file. filename = directory + DIRECTORY_IMAGES + name + '.jpg' image_data = tf.gfile.FastGFile(filename, 'rb').read() # Read the XML annotation file. filename = os.path.join(directory, DIRECTORY_ANNOTATIONS, name + '.xml') tree = ET.parse(filename) root = tree.getroot() # Image shape. size = root.find('size') shape = [int(size.find('height').text), int(size.find('width').text), int(size.find('depth').text)] # Find annotations. bboxes = [] labels = [] labels_text = [] difficult = [] truncated = [] for obj in root.findall('object'): label = obj.find('name').text labels.append(int(VOC_LABELS[label][0])) labels_text.append(label.encode('ascii')) # 变为ascii格式 if obj.find('difficult'): difficult.append(int(obj.find('difficult').text)) else: difficult.append(0) if obj.find('truncated'): truncated.append(int(obj.find('truncated').text)) else: truncated.append(0) bbox = obj.find('bndbox') a = float(bbox.find('ymin').text) / shape[0] b = float(bbox.find('xmin').text) / shape[1] a1 = float(bbox.find('ymax').text) / shape[0] b1 = float(bbox.find('xmax').text) / shape[1] a_e = a1 - a b_e = b1 - b if abs(a_e) < 1 and abs(b_e) < 1: bboxes.append((a, b, a1, b1)) return image_data, shape, bboxes, labels, labels_text, difficult, truncated def _convert_to_example(image_data, labels, labels_text, bboxes, shape,difficult, truncated): """ 转化样例 """ xmin = [] ymin = [] xmax = [] ymax = [] for b in bboxes: assert len(b) == 4 # pylint: disable=expression-not-assigned [l.append(point) for l, point in zip([ymin, xmin, ymax, xmax], b)] # pylint: enable=expression-not-assigned image_format = b'JPEG' example = tf.train.Example(features=tf.train.Features(feature={ 'image/height': int64_feature(shape[0]), 'image/width': int64_feature(shape[1]), 'image/channels': int64_feature(shape[2]), 'image/shape': int64_feature(shape), 'image/object/bbox/xmin': float_feature(xmin), 'image/object/bbox/xmax': float_feature(xmax), 'image/object/bbox/ymin': float_feature(ymin), 'image/object/bbox/ymax': float_feature(ymax), 'image/object/bbox/label': int64_feature(labels), 'image/object/bbox/label_text': bytes_feature(labels_text), 'image/object/bbox/difficult': int64_feature(difficult), 'image/object/bbox/truncated': int64_feature(truncated), 'image/format': bytes_feature(image_format), 'image/encoded': bytes_feature(image_data)})) return example def _add_to_tfrecord(dataset_dir, name, tfrecord_writer): """ 增加到tfrecord """ image_data, shape, bboxes, labels, labels_text, difficult, truncated = \ _process_image(dataset_dir, name) example = _convert_to_example(image_data, labels, labels_text, bboxes, shape, difficult, truncated) tfrecord_writer.write(example.SerializeToString()) def _get_output_filename(output_dir, name, idx): """ name为转化文件的前缀 """ return '%s/%s_%03d.tfrecord' % (output_dir, name, idx) def run(dataset_dir, output_dir, name='voc_train', shuffling=False): if not tf.gfile.Exists(dataset_dir): tf.gfile.MakeDirs(dataset_dir) path = os.path.join(dataset_dir, DIRECTORY_ANNOTATIONS) filenames = sorted(os.listdir(path)) if shuffling: random.seed(RANDOM_SEED) random.shuffle(filenames) i = 0 fidx = 0 while i < len(filenames): # Open new TFRecord file. tf_filename = _get_output_filename(output_dir, name, fidx) with tf.python_io.TFRecordWriter(tf_filename) as tfrecord_writer: j = 0 while i < len(filenames) and j < SAMPLES_PER_FILES: sys.stdout.write(' Converting image %d/%d \n' % (i + 1, len(filenames))) # 终端打印,类似print sys.stdout.flush() # 缓冲 filename = filenames[i] img_name = filename[:-4] _add_to_tfrecord(dataset_dir, img_name, tfrecord_writer) i += 1 j += 1 fidx += 1 print('\nFinished converting the Pascal VOC dataset!') def main(_): # 原数据集路径,输出路径以及输出文件名,要根据自己实际做改动 dataset_dir = "../VOC2007_test/" output_dir = "tfrecords_/" if not os.path.exists(output_dir): os.mkdir(output_dir) run(dataset_dir, output_dir) if __name__ == '__main__': tf.app.run()
得到的.tfrecords文件如下:
到这里,用于SSD的自己的数据集就建立完成了,主要需要的就是.tfrecords
文件。下一章 SSD目标检测(3):使用自己的数据集做识别(详细说明附源码)介绍如何用自己的数据集开展训练预测
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。