TensorFlow Object Detection API 训练并调用自己的模型
声明:本文是参照这篇博客而记录的一些总结笔记,包含了我遇到的一些问题和注意事项,当作课代表的总结看就行了,更加详细的内容请参考原文博客。
准备训练样本并标注
安装使用labelImg工具标注 生成xml文件
labelImg工具的安装
请参考这里上述链接很详细的讲了Windows/Linux上的源码安装以及后面补充的windows上的打包好的软件,这里我推荐直接使用大佬们打包好的软件,解压即用很方便。不过需要注意的一点是路径不要有中文。不然会出现弹出一个框然后就退出的情况!可能上面的链接下载需要科学上网,这里我上传一个我自己使用的windows1.80版本的百度云提取码 lk0m 。
使用labelImg工具标注并生成xml文件
在 \windows_v1.8.1\data\路径下有一个predefined_classes.txt的文本,里面有一些分类,生成自己的数据集需要把其中的分类改成自己需要的方便一会标注。推荐使用Notepad++打开,如果直接用记事本打开里面是不换行的,不是很方便。
将里面的分类替换成你自己的分类之后打开 \windows_v1.8.1\labelImg.exe ,操作如下图,注意图片格式一定要为.jpg .JPG格式
标注完成后点Save就会在你指定的目录生成对应名字的xml文件,里面记录的图片的名字,路径以及分类的名字,位置。这里图片的路径并不影响后面的步骤。
把xml文件转换成 TFRecords Format 格式
把xml文件转换成csv表格
使用xml_to_csv_js.py 把xml文件转换成csv表格
1.更改文件所在目录和生成目录,生成目录和文件目录一致即可2.同时更改生成文件名字,train与test 区分
import os
import glob
import pandas as pd
import xml.etree.ElementTree as ET
os.chdir('C:/Users/JIA/Desktop/test')
path = 'C:\\Users\\JIA\\Desktop\\test\\'
def xml_to_csv(path):
xml_list = []
for xml_file in glob.glob(path + '/*.xml'):
tree = ET.parse(xml_file)
root = tree.getroot()
for member in root.findall('object'):
value = (root.find('filename').text,
int(root.find('size')[0].text),
int(root.find('size')[1].text),
member[0].text,
int(member[4][0].text),
int(member[4][1].text),
int(member[4][2].text),
int(member[4][3].text)
)
xml_list.append(value)
column_name = ['filename', 'width', 'height', 'class', 'xmin', 'ymin', 'xmax', 'ymax']
xml_df = pd.DataFrame(xml_list, columns=column_name)
return xml_df
def main():
image_path = path
xml_df = xml_to_csv(image_path)
xml_df.to_csv('test_labels.csv', index=None)
print('Successfully converted xml to csv.')
main()
把csv文件转换成 TFRecords Format 格式
1.更改图片所在目录 csv所在目录 文件生成目录
2.注意更改label类别
"""
import os
import io
import pandas as pd
import tensorflow as tf
from PIL import Image
from object_detection.utils import dataset_util
from collections import namedtuple, OrderedDict
os.chdir('C:\\Users\\JIA\\Desktop\\test\\')
flags = tf.app.flags
flags.DEFINE_string('csv_input', 'C:/Users/JIA/Desktop/test/test_labels.csv', 'Path to the CSV input')
flags.DEFINE_string('output_path', 'C:/Users/JIA/Desktop/test/test.record', 'Path to output TFRecord')
FLAGS = flags.FLAGS
# TO-DO replace this with label map
# 注意将对应的label改成自己的类别!!!!!!!!!!
def class_text_to_int(row_label):
if row_label == 'red_tri':
return 1
elif row_label == 'red_yuan':
return 2
elif row_label == 'red_rect':
return 3
else:
None
def split(df, group):
data = namedtuple('data', ['filename', 'object'])
gb = df.groupby(group)
return [data(filename, gb.get_group(x)) for filename, x in zip(gb.groups.keys(), gb.groups)]
def create_tf_example(group, path):
with tf.gfile.GFile(os.path.join(path, '{}'.format(group.filename)), 'rb') as fid:
encoded_jpg = fid.read()
encoded_jpg_io = io.BytesIO(encoded_jpg)
image = Image.open(encoded_jpg_io)
width, height = image.size
filename = group.filename.encode('utf8')
image_format = b'jpg'
xmins = []
xmaxs = []
ymins = []
ymaxs = []
classes_text = []
classes = []
for index, row in group.object.iterrows():
xmins.append(row['xmin'] / width)
xmaxs.append(row['xmax'] / width)
ymins.append(row['ymin'] / height)
ymaxs.append(row['ymax'] / height)
classes_text.append(row['class'].encode('utf8'))
classes.append(class_text_to_int(row['class']))
tf_example = tf.train.Example(features=tf.train.Features(feature={
'image/height': dataset_util.int64_feature(height),
'image/width': dataset_util.int64_feature(width),
'image/filename': dataset_util.bytes_feature(filename),
'image/source_id': dataset_util.bytes_feature(filename),
'image/encoded': dataset_util.bytes_feature(encoded_jpg),
'image/format': dataset_util.bytes_feature(image_format),
'image/object/bbox/xmin': dataset_util.float_list_feature(xmins),
'image/object/bbox/xmax': dataset_util.float_list_feature(xmaxs),
'image/object/bbox/ymin': dataset_util.float_list_feature(ymins),
'image/object/bbox/ymax': dataset_util.float_list_feature(ymaxs),
'image/object/class/text': dataset_util.bytes_list_feature(classes_text),
'image/object/class/label': dataset_util.int64_list_feature(classes),
}))
return tf_example
def main(_):
writer = tf.python_io.TFRecordWriter(FLAGS.output_path)
path = os.path.join(os.getcwd(), '')
examples = pd.read_csv(FLAGS.csv_input)
grouped = split(examples, 'filename')
for group in grouped:
tf_example = create_tf_example(group, path)
writer.write(tf_example.SerializeToString())
writer.close()
output_path = os.path.join(os.getcwd(), FLAGS.output_path)
print('Successfully created the TFRecords: {}'.format(output_path))
if __name__ == '__main__':
tf.app.run()
.各类文件所在目录以及生成文件
使用自己的数据集训练模型
注意 !!从这里开始路径位置都是关联对应的!
1.在 \research\object_detection\data 目录下新建一个data和images目录 data目录下放入test和train的.csv .record文件共4个文件 images 文件下新建test 和 train 文件存放的时.jpg图片和xml文件
注意 !!我在这里data路径下又新建了一个data,这里跟原文略略不同但是后面跟着我路径统一了就没问题
2.在\research\object_detection\data 目录下新建一个 mat.pbtxt 文件 名字随意注意与后面路径统一 内容与训练类别对应
这里贴出部分内容,按照这个格式就行了
item {
id: 1
name: 'red_tri'
}
item {
id: 2
name: 'red_yuan'
}
item {
id: 3
name: 'red_rect'
}
item {
id: 4
name: 'red_lingx'
}
item {
id: 5
name: 'red_five'
}
3.在\research\object_detection目录下 创建training 文件夹 进入research/object_detection/samples/configs/目录下 以 ssd_mobilenet_v1_coco.config 为例,将ssd_mobilenet_v1_coco.config 放在training 文件夹下,用文本编辑器打开 ,进行如下操作:
1、搜索其中的 PATH_TO_BE_CONFIGURED ,将对应的路径改为自己的路径,注意不要把test跟train弄反了;
2、将 num_classes 按照实际情况更改;
3、batch_size 原本是24,我在运行的时候出现显存不足的问题,为了保险起见,改为1,如果1还是出现类似问题的话,建议换电脑……
4、fine_tune_checkpoint: “ssd_mobilenet_v1_coco_11_06_2017/model.ckpt”
from_detection_checkpoint: true
这两行是设置checkpoint,我开始也设置,但是一直出现显存不足的问题,我的理解是从预先训练的模型中寻找checkpoint,可能是因为原先的模型是基于较大规模的公开数据集训练的,因此配置到本地的时候出现了问题,后来我选择删除这两行,相当于自己从头开始训练,最后正常了,因此如果是自己从头开始训练,建议把这两行删除。
这里需要注意文件的存放路径
刚才我的map.pbtxt文件是在\research\object_detection\data 路径下 而.record 文件是在\research\object_detection\data\data 文件下,所以这里的路径需要注意
4.训练
官方给了新旧两种训练文件,
一个是\research\object_detection 路径下的model_main.py
一个是\research\object_detection\legacy 路径下的 train.py
这里可以把 train.py也放到\research\object_detection 路径下。
第一种,在\research\object_detection目录下打开cmd 输入:
python model_main.py --pipeline_config_path=training/ssd_mobilenet_v1_coco.config --model_dir=training --num_train_steps=50000 --num_eval_steps=2000 --alsologtostderr
这里如果想要像第二种一样显示loss,需要打开train.py文件把第55行的
tf.logging.set_verbosity(tf.logging.INFO)
复制到model_main.py文件中,就可以每100步查看一次loss。
第二种,在\research\object_detection目录下打开cmd 输入:
python train.py --logtostderr --train_dir=training/ --pipeline_config_path=training/ssd_mobilenet_v1_coco.config
这是原文的图,我直接搬过来了
5.等待期间可以查看tensorboard
在\research\object_detection目录下进入cmd 输入 tensorboard --logdir=training
将生成的网址复制粘贴到浏览器中就可以查看了
6.冻结权重,生成.pb等文件
在\research\object_detection目录下打开cmd 输入
python export_inference_graph.py --input_type image_tensor -pipeline_config_path training/ssd_mobilenet_v1_coco.config --trained_checkpoint_prefix training/model.ckpt-20624 --output_directory new_models
new_models 在当前\object_detection 下创建一个 new_models文件夹 存放生成文件
–output_directory 后面的文件夹是生成文件存放的地方可以自己定义
–trained_checkpoint_prefix training/model.ckpt-20624 后面的数字是要查看自己training文件夹中.ckpt文件后面最大的步数
调用验证模型
1.在 \research\object_detection目录下打开cmd 输入 jupyter notebook 打开jupyter 注意不要关闭cmd
2.打开object_detection_tutorial.ipynb创建一个copy副本
3.修改
4.将测试图片改好名字放入test_images文件夹下,然后运行RunAll
希望这篇文章对您有帮助,感谢阅读!