tensorflow(cpu)-object-detection-api安装并训练自己的模型(Ubuntu)避坑备忘录

网上有蛮多的指导虽然,但是大佬们有些细节不那么细,或者是版本比较老了,或者是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(cpu)-object-detection-api安装并训练自己的模型(Ubuntu)避坑备忘录

三 下载tensorflow object detection api

如果你是最新tensorflow 直接下载使用即可

下载地址:GitHub - tensorflow/models: Models and examples built with TensorFlow

这里我使用的是tensorflow1.15,所以我选择了r1.13的分支。

tensorflow(cpu)-object-detection-api安装并训练自己的模型(Ubuntu)避坑备忘录

四 编译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

运行后如下图

tensorflow(cpu)-object-detection-api安装并训练自己的模型(Ubuntu)避坑备忘录

然后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

会返回一个网址,在浏览器打开这个网址,你可以看到损失曲线。

tensorflow(cpu)-object-detection-api安装并训练自己的模型(Ubuntu)避坑备忘录

 tensorflow(cpu)-object-detection-api安装并训练自己的模型(Ubuntu)避坑备忘录

 本来还想再细一点,再加个预测的,中文不太方便,就只写这么多,应该网上也有类似的教程

上一篇:Python 20行代码检测人脸是否佩戴口罩


下一篇:Java:检测对文件的修改(文件轮询?)