网上有蛮多的指导虽然,但是大佬们有些细节不那么细,或者是版本比较老了,或者是gpu版的,gpu版按照网上的装驱动和cuda我的系统挂了5次,只好老实用cpu版的,虽然是tf1.x的,但同时也扩展了一点tf2的,希望对大家有所帮助。
相关库依赖
Python=3.6####不要小看这里,python版本过高,和tensorflow版本,numpy版本形成死循环,导致你无法找到合适的numpy版本,出现ValueError: numpy.ndarray size changed, may indicate binary incompatibility. Expected 88 from C header, got 80 from PyObject.和NotImplementedError: Cannot convert a symbolic Tensor (strided_slice:0) to a numpy array,相信你不愿意训练的时候跟题主一样受折磨。
Tensorflow=1.15.0 环境
Matplotlib 文件处理所需
Pandas 文件转化所需
Jupyter 测试环境所需
Protobuf 编译所需
Pillow 图片处理所需
Cython 安装cocoapi所需
Lxml 标注工具所需
一 安装anaconda创建虚拟环境
$ Sudo chmod 755 Ana-------.sh
$./Ana-----.sh
安装过程选择yes即可
创建虚拟环境:
$conda create –n tf1 python=3.6
$conda activate tf1
之后操作均需要在tf1环境中进行,在新建terminal或者更新环境变量后,记得重新激活环境。
二 配置环境:
第一步中python3.6基本环境已经创建,安装tensorflow以及相关依赖环境:
Conda install tensorflow==1.15.0
Conda install matplotlib pandas jupyter protobuf pillow cython lxml
如果你不太清楚有哪些版本,推荐在anaconda-navigator进入界面进入enviroments,看到你所需要的环境,为其配置特定版本的包和依赖。
三 下载tensorflow object detection api
如果你是最新tensorflow 直接下载使用即可
下载地址:GitHub - tensorflow/models: Models and examples built with TensorFlow
这里我使用的是tensorflow1.15,所以我选择了r1.13的分支。
四 编译protocbuf(一般来说你安装tensorflow后anaconda自动安装protobuf,请确保版本3.x)
$:cd model-master/research
$: protoc --python_out=. object_detection/protos/*.proto
这里会看到object_detection/protos目录下新生成一些新py文件
五安装coco(可选)tf2好像必须装,好像还得按顺序,反正你按照我的顺序装就行
如果你不是用coco相关模型可以不装
下载地址:GitHub - cocodataset/cocoapi: COCO API - Dataset @ http://cocodataset.org/
使用的话,下载地址记得将cocoeval.py文件里的这两个地方改一下,否则训练会报错,什么numpy不能执行非整形的步长。
self.iouThrs = np.linspace(.5, 0.95, np.round((0.95 - .5) / .05) + 1, endpoint=True)
self.recThrs = np.linspace(.0, 1.00, np.round((1.00 - .0) / .01) + 1, endpoint=True)
改成
self.iouThrs = np.linspace(.5, 0.95, int(np.round((0.95 - .5) / .05) + 1), endpoint=True)
self.recThrs = np.linspace(.0, 1.00, int(np.round((1.00 - .0) / .01) + 1), endpoint=True)
$:cd coco-master/Pythonapi
$python setup.py install
六 安装object detection和slim,配置变量
$:python setup.py install
$:cd slim
$python setup.py install
$cd ..
$gedit ~/.bashrc
在.bashrc文件后面添加
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
$source ~/.bashrc
(注意:这里更新完系统变量后,会重新进入base环境记得激活tf1。后续如果出现no module named net“错误,说明你slim没装好,no module named object-detection,说明你research下的安装没装好,重新安装即可。如果你使用tf2,在research需要从object-detection复制setup.py: cp object_detection/packages/tf2/setup.py .
七 测试一下安装情况
$: python object_detection/builders/model_builder_test.py
正常安装会显示ok和测试时间
$:jupyter notebook(这里如果没在tf1环境下安装jupyter包,你所打开的jupyter notebook会是base环境下,所以出现no module类似错误不妨检查一下jupyter是否在tf1安装)
打开object-detection下的object_detection_tutorial.ipynb,运行(tf2版本的放在colab_ tutorials文件下)
没问题的话,应该可以看到那只狗和放风筝的图。
至此tensorflow object detection api搭建完毕。
由于后面设计文件存放的操作,我把操作中涉及到的文件目录放在这里
object-detection.
├── data
│ ├── images
│ │ ├── test
│ │ └── train
│ ├── mushroom.pbtxt
│ ├── test.csv
│ ├── test.record
│ ├── train.csv
│ ├── train.record
│ └── tree.txt
├── training
│ └── ssd-mo-v1-coco
│ ├── checkpoint
│ ├── frozen_inference_graph.pb
│ ├── model.ckpt.data-00000-of-00001
│ ├── model.ckpt.index
│ ├── model.ckpt.meta
│ ├── pipeline.config
│ └── saved_model
八 制作标签文件数据集
首先你已经收集到了所需的图片文件(建议命名为:统一名称+序号),然后你需要对这些文件进行标记,建议使用lableimg,可以生成xml文件。(注意xml文件是包含路径的,故无法使用简单的复制粘贴,后面生成的csv文件只是指定文件名称,不含路径,可移植,record文件因为已经包含图片和xml信息所以也可以移植。备份文件请记住这一点)每一个文件会生成一个xml文件
下载安装方式:
下载或者克隆地址:https://github.com/Ruolingdeng/labelImg
这里使用python3和qt5
进入lableimg目录
$sudo apt-get install pyqt5-dev-tools
$sudo pip3 install -r requirements/requirements-linux-python3.txt
$make qt5py3
$python3 labelImg.py
运行后如下图
然后open dir打开确定你存放图片的路径,change save dir确定你要存放xml文件的路径,绘制标签框,一张图可以绘制多个标签,标记后save,切换到下一张。
九数据集的转换xml-csv,csv-record
先将xml文件转化为csv文件,下面是转化的相关代码,需要的话,将它粘贴到xml-csv.py文件,python xml-csv.py运行文件即可,可能需要修改的部分用红字标出
import os
import glob
import pandas as pd
import xml.etree.ElementTree as ET
os.chdir('/home/aaeon/tensorflow/model/research/object_detection/data/images/train')
#工作目录,根据你所需要处理的图片路径。转换测试集再进行修改。
path = '/home/aaeon/tensorflow/model/research/object_detection/data/images/train’
#csv文件保存的路径,一般和上面工作目录相同
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('train.csv', index=None)#修改你要生成的csv文件名,测试集:test.csv
print('Successfully converted xml to csv.')
main()
分别对训练集和测试集进行转化,执行两次xml-csv文件,红色字体部分记得检查和修改。
转化成功会打印出Successfully converted xml to csv。
Csv到record的转化,同样复制下面的代码到generate_tfrecord.py里面,根据要求修改后,分别执行:
$python generate_tfrecord.py --csv_input=data/train.csv --output_path=data/train.record
$ python generate_tfrecord.py --csv_input=data/test.csv --output_path=data/test.record
执行成功后,会看到两个record文件,分别是train.record和test.record
# generate_tfrecord.py
# -*- coding: utf-8 -*-
"""
Usage:
# From tensorflow/models/
# Create train data:
python generate_tfrecord.py --csv_input=data/train.csv --output_path=data/train.record
# Create test data:
python generate_tfrecord.py --csv_input=data/test.csv --output_path=data/test.record
"""
import os
import io
import pandas as pd
import tensorflow as tf
from PIL import Image
from object_detection.utils import dataset_util
flags = tf.app.flags
flags.DEFINE_string('csv_input', '', 'Path to the CSV input')
flags.DEFINE_string('output_path', '', 'Path to output TFRecord')
FLAGS = flags.FLAGS
# 需要修改类别标签
def class_text_to_int(row_label):
if row_label == 'mushroom':
return 1
else:
None
def create_tf_example(row):
#full_path = os.path.join(os.getcwd(), 'images', '{}'.format(row['filename']))
full_path = os.path.join(os.path.dirname(FLAGS.csv_input), 'images/train', '{}'.format(row['filename']))
#这里对图片存放的路径,我这里是将图片images放到了data文件夹下面,测试图片和训练图片分开,所以两次执行前都需要修改
with tf.gfile.GFile(full_path, '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 = row['filename'].encode('utf8')
image_format = b'jpg'
xmins = [row['xmin'] / width]
xmaxs = [row['xmax'] / width]
ymins = [row['ymin'] / height]
ymaxs = [row['ymax'] / height]
classes_text = [row['class'].encode('utf8')]
classes = [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)
examples = pd.read_csv(FLAGS.csv_input)
for index, row in examples.iterrows():
tf_example = create_tf_example(row)
writer.write(tf_example.SerializeToString())
writer.close()
if __name__ == '__main__':
tf.app.run()
至此,需要的训练数据文件和测试文件已经生成完毕。
九 修改模型配置文件
你可以在网络上选择你想要的模型下载;
Tf1: models/tf1_detection_zoo.md at master · tensorflow/models · GitHub
Tf2: models/tf2_detection_zoo.md at master · tensorflow/models · GitHub
或者在本地找到config文件:
Tf1一般在:object-detection/samples/configs
Tf2:一般在:object-detection/config
这里tensorflow1.x就使用tf1的模型。Tf2请使用tf2的模型一一对应不要增加自己的负担。
我这里使用的是ssd-mobilenet-coco模型,修改包括以下几个位置,其他模型类似,找到对应位置修改即可
model {
ssd {
num_classes: 1 #####编辑你的num_class#####
#识别种类类别数目,我这里只有一种就为1,
image_resizer {
fixed_shape_resizer {
height: 300
width: 300
}
}
feature_extractor {
type: "ssd_inception_v2"
depth_multiplier: 1.0
min_depth: 16
conv_hyperparams {
regularizer {
l2_regularizer {
weight: 3.99999989895e-05
}
}
initializer {
truncated_normal_initializer {
mean: 0.0
stddev: 0.0299999993294
}
}
activation: RELU_6
batch_norm {
decay: 0.999700009823
center: true
scale: true
epsilon: 0.0010000000475
train: true
}
}
override_base_feature_extractor_hyperparams: true
}
box_coder {
faster_rcnn_box_coder {
y_scale: 10.0
x_scale: 10.0
height_scale: 5.0
width_scale: 5.0
}
}
matcher {
argmax_matcher {
matched_threshold: 0.5
unmatched_threshold: 0.5
ignore_thresholds: false
negatives_lower_than_unmatched: true
force_match_for_each_row: true
}
}
similarity_calculator {
iou_similarity {
}
}
box_predictor {
convolutional_box_predictor {
conv_hyperparams {
regularizer {
l2_regularizer {
weight: 3.99999989895e-05
}
}
initializer {
truncated_normal_initializer {
mean: 0.0
stddev: 0.0299999993294
}
}
activation: RELU_6
}
min_depth: 0
max_depth: 0
num_layers_before_predictor: 0
use_dropout: false
dropout_keep_probability: 0.800000011921
kernel_size: 3
box_code_size: 4
apply_sigmoid_to_scores: false
}
}
anchor_generator {
ssd_anchor_generator {
num_layers: 6
min_scale: 0.20000000298
max_scale: 0.949999988079
aspect_ratios: 1.0
aspect_ratios: 2.0
aspect_ratios: 0.5
aspect_ratios: 3.0
aspect_ratios: 0.333299994469
reduce_boxes_in_lowest_layer: true
}
}
post_processing {
batch_non_max_suppression {
score_threshold: 0.300000011921
iou_threshold: 0.600000023842
max_detections_per_class: 100
max_total_detections: 100
}
score_converter: SIGMOID
}
normalize_loss_by_num_matches: true
loss {
localization_loss {
weighted_smooth_l1 {
}
}
classification_loss {
weighted_sigmoid {
}
}
hard_example_miner {
num_hard_examples: 3000
iou_threshold: 0.990000009537
loss_type: CLASSIFICATION
max_negatives_per_positive: 3
min_negatives_per_image: 0
}
classification_weight: 1.0
localization_weight: 1.0
}
}
}
train_config {
batch_size: 24 #####batch_size根据你的内存更改#####
data_augmentation_options {
random_horizontal_flip {
}
}
data_augmentation_options {
ssd_random_crop {
}
}
optimizer {
rms_prop_optimizer {
learning_rate {
exponential_decay_learning_rate {
initial_learning_rate: 0.00400000018999
decay_steps: 800720
decay_factor: 0.949999988079
}
}
momentum_optimizer_value: 0.899999976158
decay: 0.899999976158
epsilon: 1.0
}
}
fine_tune_checkpoint: "training/ssd_mobilenet_ _coco/model.ckpt" #####更改路径#####
from_detection_checkpoint: true
#补充一点,这两句是要从你给定的文件夹读取初始参数,如果你没有相关文件或者不想提供相关文件可以注释掉
num_steps: 200000 #####更改steps数目#####
}
train_input_reader {
label_map_path: "data /mushroom.pbtxt" #####更改标签文件路径#####
tf_record_input_reader {
input_path: "data/train.record" #####更改训练文件路径#####
}
}
eval_config {
num_examples: 8000
max_evals: 10
use_moving_averages: false
}
eval_input_reader {
label_map_path: "data/mushroom.pbtxt" #####更改标记文件路径#####
shuffle: false
num_readers: 1
tf_record_input_reader {
input_path: "data/test.record" #####更改测试文件路径#####
}
}
如果你细心的话,就会发现我们上面引入标记文件,然后需要在data文件生成标记文件,文件类型是pbtxt,在其中填入你识别的类别:
我的只有mushroom像这样:
item {
name: "mushroom"
id: 1
display_name: "mushroom"
}
红色字体需要根据你generate_tfrecord.py里面的标签类别修改外,其他复制粘贴即可。
至此,文件已经准备结束。
十模型训练和tensorbroad观察
在object-detection下执行(tf2请使用 model_main_tf2.py)
python model_main.py
--model_dir=training/ssd-mo-v1-coco/saved_model/ --pipeline_config_path=training/ssd-mo-v1-coco/pipeline.config
--num_train_steps=1000
--num_eval_steps=10
--alsologtostderr
model_dir:模型存放路径
pipeline_config_path:配置文件读取路径
num_train_steps:训练步数
num_eval_steps:测试步数
运行没问题就会慢慢运行,并展示步数对应的loss。
对模型可视化:
在object_detection路径下:
$ tensorboard --logdir=training
会返回一个网址,在浏览器打开这个网址,你可以看到损失曲线。
本来还想再细一点,再加个预测的,中文不太方便,就只写这么多,应该网上也有类似的教程