0 背景

在之前的文章中,对 tensorflow 目标检测API进行了详细的测试,成功应用其模型做简单的检测任务。首先简单介绍下系统环境的配置

python3.6; tensorflow-gpu 1.10; cuda 9.0

安装步骤

conda create -n deeplab python=3.6
source activate deeplab
pip install tensorflow-gpu==1.10.0
# pip 安装不上的话,直接下载 whl 二进制文件安装
# 下载路径:https://pypi.org/project/tensorflow-gpu/git clone https://github.com/tensorflow/models.git# cd进入tensorflow/models/research/目录,将下边目录加到环境变量中
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim# 为了避免每个终端都重复输入,可以将该环境变量写到 ~/.bashrc 文件中,但注意要写绝对路径

配置完后可以运行测试

# From tensorflow/models/research/
python deeplab/model_test.py

正确输出OK即没问题,接下来对训练自己的数据做一介绍

1 文件结构

首先在 research/deeplab/datasets 下新建一个文件夹,这里我建的是 loulan,用来做漏缆的语义分割。然后在文件夹下新建 dataset、init_models、tfrecord 和 train 子文件夹

loulan
.
├── dataset
│   ├── ImageSets
│   ├── JPEGImages
│   ├── SegmentationClass
│   ├── SegmentationClassRaw
├── init_models
├── tfrecord
└── train

2 准备数据

这一步操作都在 loulan/dataset 文件夹中。

2.1 原始数据

首先使用《图片标注工具Labelme的安装及使用方法》中的方法完成语义分割图像标注,生成 png 标注图片

2.2 转化灰度图

接下来要将上一步的标注文件转化为单通道的灰度图,用不同的像素值来表示不同的类别。

在 datasets 文件夹下有一个 remove_gt_colormap.py 文件,我们只需要指定输入图片路径和输出图片路径即可

python remove_gt_colormap.py --original_gt_folder=./loulan/dataset/SegmentationClass --output_dir=./loulan/dataset/SegmentationClassRaw

运行后会在 SegmentationClassRaw 文件夹里生成标签图,肉眼看上去是全黑的图片,我们可以使用像素查看工具查看生成的图片像素值,可以看到像素不为0

或者使用《Python之OpenCV直方图统计及均衡化》 中的方法统计一下灰度图的直方图,可以看到不止有 0 一种像素(坐标50 100 150 显示依次对应的是 0 1 2 像素)

2.3 数据分类

在 loulan/dataset/ImageSets 文件夹下新建三个文本文件,分别是 train.txt、trainval.txt、val.txt,然后将标注的数据的文件名按照训练集:验证集 = 4:1的比例分别保存于 train.txt 和 val.txt,然后把所有的名字保存在 trainval.txt 中。可参考我以下方法保存

# -*- coding:utf8 -*-
import osimgpath = "./loulan/dataset/JPEGImages/"
savedpath = "./loulan/dataset/ImageSets/"filelist = os.listdir(imgpath)with open(savedpath + "train.txt", "w") as f:i = 0for item in filelist:i += 1# print('item name is ',item)if i % 5 != 0:name = item.split(".png",1)[0]f.write(name + "\n")with open(savedpath + "val.txt", "w") as f:i = 0for item in filelist:i += 1# print('item name is ',item)if i % 5 == 0:name = item.split(".png",1)[0]f.write(name + "\n")with open(savedpath + "trainval.txt", "w") as f:i = 0for item in filelist:name = item.split(".png",1)[0]f.write(name + "\n")            

生成的 txt 文件中只保留图片的名字,格式如下

20190312212459
20190315080932
20190309103725
20190314204416
20190314235212
20190313064321
20190311021339
20190309080810
20190314064900

2.4 生成tfrecord

在 deeplab/datasets 文件夹下,有生成 tfrecord 的程序,因为我们采用的是 voc 数据结构,因此需运行 build_voc2012_data.py,具体参数如下

python ./build_voc2012_data.py --image_folder="./loulan/dataset/JPEGImages" --semantic_segmentation_folder="./loulan/dataset/SegmentationClassRaw" --list_folder="./loulan/dataset/ImageSets" --image_format='jpg' --output_dir="./loulan/tfrecord"

运行成功后生成如下文件

3 网络训练

3.1 预训练模型下载

官方提供了不少预训练模型,这里以 deeplabv3_pascal_train_aug_2018_01_04 为例

在 loulan/init_models 文件夹中下载解压模型,得到 deeplabv3_pascal_train_aug 文件夹

wget http://download.tensorflow.org/models/deeplabv3_pascal_train_aug_2018_01_04.tar.gz
tar zxf deeplabv3_pascal_train_aug_2018_01_04.tar.gz

3.2 数据集描述

在 deeplab/datasets 文件夹下,有一个 segmentation_dataset.py 或 data_generator.py 文件,用来描述我们数据集,打开之后添加如下代码

首先在 _DATASETS_INFORMATION 中添加如下

_DATASETS_INFORMATION = {'cityscapes': _CITYSCAPES_INFORMATION,'pascal_voc_seg': _PASCAL_VOC_SEG_INFORMATION,'ade20k': _ADE20K_INFORMATION,'loulan': _LOULAN_INFORMATION,
}

然后与 _ADE20K_INFORMATION 并列关系,添加如下代码

_LOULAN_INFORMATION = DatasetDescriptor(splits_to_sizes={'train': 824, # 训练集的图片数量'trainval': 1030,  #所有图片数量'val': 206,  #验证集的图片数量},num_classes=4, # 数据类别,包含 background 和 ignore_lableignore_label=255, # 忽略的类别
)

3.3 修改类别

如果自己的训练类别数发生变化,需要在 utils/train_utils.py 中,将大概109行的关于exclude_list的设置修改,作用是在使用预训练权重时候,不加载该logit层,否则加载预训练时会报类别错误问题

# Variables that will not be restored.
exclude_list = ['global_step','logits']
if not initialize_last_layer:
exclude_list.extend(last_layers)

3.4 开始训练

在 deeplab 下,有一个 train.py 文件,我们只需要把参数设置好即可,具体如下

CUDA_VISIBLE_DEVICES=2,3,4,5 python train.py \
--logtostderr \
--num_clones=4  \
--training_number_of_steps=10000 \
--train_split="train" \
--model_variant="xception_65" \
--atrous_rates=6 \
--atrous_rates=12 \
--atrous_rates=18 \
--output_stride=16 \
--decoder_output_stride=4 \
--train_crop_size=513 \
--train_crop_size=513 \
--train_batch_size=4 \
--fine_tune_batch_norm=False \
--tf_initial_checkpoint="./datasets/loulan/init_models/deeplabv3_pascal_trainval/model.ckpt" \
--train_logdir="./datasets/loulan/train/" \
--dataset="loulan" \
--dataset_dir="./datasets/loulan/tfrecord/"

参数说明:

  • --num_clones=4 表示在4块GPU上进行训练,要根据自己显卡数量进行配置
  • 如果显卡足够强,batch_size能设置的大于12时,要将 fine_tune_batch_norm 设置为 True
  • train_crop_size 要满足 (crop_size - 1)/4 = 整数,且不得小于 321
  • 注意 train_crop_size 的写法,在新版本中已经统一为 --train_crop_size=513,513 的形式,而不是分开写,否则会报错,参考 https://github.com/tensorflow/models/issues/6804#issuecomment-493421542
  • 使用预训练的所有权重,设置 initialize_last_layer=True
  • 只使用网络的backbone,设置 initialize_last_layer=False 和 last_layers_contain_logits_only=False
  • 使用所有的预训练权重,除了logits,因为如果是自己的数据集,对应的 classes 不同,可设置 initialize_last_layer=False 和 last_layers_contain_logits_only=True

训练的时候,可以用tensorboard --logdir='train' 来观察loss的变化,如果loss趋于稳定,就可以停止训练了

3.5 导出模型

训练后在 loulan/train 文件夹下生成一些结果文件,如

  • graph.pbtxt
  • model.ckpt-1000.data-00000-of-00001
  • model.ckpt-1000.info
  • model.ckpt-1000.meta

其中 meta 文件保存了 graph 和 metadata,ckpt 文件保存了网络的 weights,进行预测时有模型的权重就够了,可以使用官方提供的脚本来生成模型文件,脚本文件是 deeplab 文件夹下 export_model.py

python export_model.py \--logtostderr \--checkpoint_path="./datasets/loulan/train/model.ckpt-22981" \--export_path="./datasets/loulan/export/frozen_inference_graph-22981.pb" \--model_variant="xception_65" \--atrous_rates=6 \--atrous_rates=12  \--atrous_rates=18 \--output_stride=16 \--decoder_output_stride=4  \--num_classes=21  \--crop_size=321  \--crop_size=321 \--inference_scales=1.0 \--num_classes=4

运行时要根据自己的文件来修改数字,运行后在 export 文件夹下生成了 frozen_inference_graph-22981.pb 文件,该模型可以在后边用来做检测。

4 模型测试

4.1 ipynb方法

在 deeplab 目录下,有一个 deeplab_demo.ipynb 文件

4.1.1 修改类别

找到以下代码修改为自己的类别

LABEL_NAMES = np.asarray(['background', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus','car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike','person', 'pottedplant', 'sheep', 'sofa', 'train', 'tv'
])

比如我只有两个类别,则改为

LABEL_NAMES = np.asarray(['background', 'lane'
])

4.1.2 载入模型

首先要将上边生成的 pb 文件压缩一下,我直接导入测试的时候报错,查看源码发现是有一个解压的过程,因此首先把文件压缩后再导入,压缩指令如下

tar zcvf frozen_inference_graph-2675.tar.gz frozen_inference_graph-2675.pb

然后把下载模型的部分注释掉,添加载入模型

#@title Select and download models {display-mode: "form"}'''
MODEL_NAME = 'mobilenetv2_coco_voctrainaug'  # @param 中间省略MODEL = DeepLabModel(download_path)
'''model_path ='./datasets/loulan/export/frozen_inference_graph-8070.tar.gz'
MODEL = DeepLabModel(model_path)print('model loaded successfully!')

4.1.3 添加测试图片

将最后一段下载 url 图片的程序注释掉,添加自己图片路径运行模型即可,如下

image_path = './datasets/loulan/dataset/JPEGImages/19678.15(20181011135748557_0).jpg'
original_im = Image.open(image_path)
resized_im, seg_map = MODEL.run(original_im)
vis_segmentation(resized_im, seg_map)

然后点击 cell-run all 即可运行出结果,效果如下

4.2 脚本测试

根据上边的 notebook,我们可以写自己的测试代码

#!/usr/bin/env python
# coding: utf-8import os
from io import BytesIO
import tarfile
import tempfile
from six.moves import urllib
from matplotlib import gridspec
from matplotlib import pyplot as plt
import numpy as np
from PIL import Image
import tensorflow as tf
import scipyLABEL_NAMES = np.asarray(["background", "class1", "class2"])class DeepLabModel(object):"""Class to load deeplab model and run inference."""INPUT_TENSOR_NAME = "ImageTensor:0"OUTPUT_TENSOR_NAME = "SemanticPredictions:0"INPUT_SIZE = 321FROZEN_GRAPH_NAME = "frozen_inference_graph"def __init__(self, modelname):"""Creates and loads pretrained deeplab model."""self.graph = tf.Graph()graph_def = Nonewith open(modelname, "rb") as fd:graph_def = tf.GraphDef.FromString(fd.read())if graph_def is None:raise RuntimeError("Cannot find inference graph in tar archive.")with self.graph.as_default():tf.import_graph_def(graph_def, name="")self.sess = tf.Session(graph=self.graph)def run(self, image):"""Runs inference on a single image.Args:image: A PIL.Image object, raw input image.Returns:resized_image: RGB image resized from original input image.seg_map: Segmentation map of `resized_image`."""width, height = image.sizeresize_ratio = 1.0 * self.INPUT_SIZE / max(width, height)target_size = (int(resize_ratio * width), int(resize_ratio * height))resized_image = image.convert("RGB").resize(target_size, Image.ANTIALIAS)batch_seg_map = self.sess.run(self.OUTPUT_TENSOR_NAME,feed_dict={self.INPUT_TENSOR_NAME: [np.asarray(resized_image)]},)seg_map = batch_seg_map[0]return resized_image, seg_mapdef create_pascal_label_colormap():"""Creates a label colormap used in PASCAL VOC segmentation benchmark.Returns:A Colormap for visualizing segmentation results."""colormap = np.zeros((256, 3), dtype=int)ind = np.arange(256, dtype=int)for shift in reversed(range(8)):for channel in range(3):colormap[:, channel] |= ((ind >> channel) & 1) << shiftind >>= 3return colormap# 从 label 到 color_image
def label_to_color_image(label):"""Adds color defined by the dataset colormap to the label.Args:label: A 2D array with integer type, storing the segmentation label.Returns:result: A 2D array with floating type. The element of the arrayis the color indexed by the corresponding element in the input labelto the PASCAL color map.Raises:ValueError: If label is not of rank 2 or its value is larger than colormap maximum entry."""if label.ndim != 2:raise ValueError("Expect 2-D input label")colormap = create_pascal_label_colormap()if np.max(label) >= len(colormap):raise ValueError("label value too large.")return colormap[label]# 分割结果可视化
def vis_segmentation(image, seg_map, name):"""Visualizes input image, segmentation map and overlay view."""plt.figure(figsize=(15, 5))grid_spec = gridspec.GridSpec(1, 4, width_ratios=[6, 6, 6, 1])plt.subplot(grid_spec[0])plt.imshow(image)plt.axis("off")plt.title("input image")plt.subplot(grid_spec[1])seg_image = label_to_color_image(seg_map).astype(np.uint8)plt.imshow(seg_image)plt.axis("off")plt.title("segmentation map")plt.subplot(grid_spec[2])plt.imshow(image)plt.imshow(seg_image, alpha=0.7)plt.axis("off")plt.title("segmentation overlay")unique_labels = np.unique(seg_map)ax = plt.subplot(grid_spec[3])plt.imshow(FULL_COLOR_MAP[unique_labels].astype(np.uint8), interpolation="nearest")ax.yaxis.tick_right()plt.yticks(range(len(unique_labels)), LABEL_NAMES[unique_labels])plt.xticks([], [])ax.tick_params(width=0.0)plt.grid("off")plt.savefig("./seg_map_result/" + name + ".png")# plt.show()FULL_LABEL_MAP = np.arange(len(LABEL_NAMES)).reshape(len(LABEL_NAMES), 1)
FULL_COLOR_MAP = label_to_color_image(FULL_LABEL_MAP)def main_test(filepath):# 加载模型modelname = "./datasets/quekou/export/frozen_inference_graph-22981.pb"MODEL = DeepLabModel(modelname)print("model loaded successfully!")filelist = os.listdir(filepath)for item in filelist:print("process image of ", item)name = item.split(".jpg", 1)[0]original_im = Image.open(filepath + item)resized_im, seg_map = MODEL.run(original_im)# 分割结果拼接vis_segmentation(resized_im, seg_map, name)# 单独保存分割结果# seg_map_name = name + '_seg.png'# resized_im_name = name + '_in.png'# path = './seg_map_result/'# scipy.misc.imsave(path + resized_im_name,resized_im)# scipy.misc.imsave(path + seg_map_name,seg_map)if __name__ == "__main__":filepath = "./datasets/quekou/dataset/JPEGImages/"main_test(filepath)

参考:https://lijiancheng0614.github.io/2018/03/13/2018_03_13_TensorFlow-DeepLab/

参考:https://medium.freecodecamp.org/how-to-use-deeplab-in-tensorflow-for-object-segmentation-using-deep-learning-a5777290ab6b

TensorFlow之DeepLabv3+训练自己的数据集相关推荐

  1. deeplabv3+训练自己的数据集

    deeplabv3+训练自己的数据集 环境:ubuntu 16.04 + TensorFlow 1.9.1 + cuda 9.0 + cudnn 7.0 +python3.6 tensorflow 项 ...

  2. deeplabv3+——训练自己的数据集 torch1.12.0 cuda11.3

    目录 前言 环境 源码 参考博客 一.制作自己的数据集 二.训练 三.可视化 前言 环境 torch==1.12.0+cu113 cuda==11.3 显卡为 RTX3070ti tips:30系显卡 ...

  3. Deeplabv3+训练自己的数据集(包含脚本)

    目录 前言 源码 一.环境配置 二.使用步骤 1.制作数据集 2.训练模型 3.测试 三.常见报错 总结 前言 最近在着手一个项目,需要用到语义分割这一块,最后经过慎重的考虑,最终选择deeplabv ...

  4. 使用 deeplabv3+ 训练自己的数据集经验总结

    简介 deeplabv3+是现今性能最好的语义分割模型之一,本文介绍如何在window环境下安装并运行deeplabv3+. 本文将详细介绍deeplabv3+的环境配置,训练自己的数据,参数调试等内 ...

  5. 【学习笔记】使用Tensorflow版ENet训练自己的数据集labelme生成灰度标签图片问题

    使用的代码:kwotsin所写的Tensorflow版,180星 记录一下训练的过程,方便以后翻阅. 首先是数据集的准备,数据集的文件夹结构为: ├── test ├── testannot ├── ...

  6. 【学习笔记】使用Tensorflow版ICNet训练自己的数据集

    所用ICNet版本:hellochick-Github,star 286 目前想在Tensorflow框架下使用ICNet训练自己的数据集,发现语义分割方面好像Tensorflow框架下的" ...

  7. DeeplabV3+ 训练自己的数据集。pytorch

    一. 代码目录 dataloaders 存放数据集读取代码 datasets 存放训练数据 modeling 存放DeeplabV3+模型文件 run_lab 保存每次训练的结果参数 test_res ...

  8. Pytorch 语义分割DeepLabV3+ 训练自己的数据集

    照葫芦画瓢总结记录了一下DeepLab分割系列,并对Deeplab V3++实现 一.DeepLab系列理解 1.DeepLab V1 原文:Semantic image segmentation w ...

  9. Win7+keras+tensorflow使用YOLO-v3训练自己的数据集

    一.下载和测试模型 1. 下载YOLO-v3 git clone https://github.com/qqwweee/keras-yolo3.git 这是在Ubuntu里的命令,windows直接去 ...

最新文章

  1. Binary Differences
  2. IoC容器总结与简单模拟
  3. J-Flash的使用
  4. [原创] 腾讯RTX二次开发相关的一些注意事项
  5. 深度窥探 QuickTest 视图(1)
  6. ARKit从入门到精通(3)-ARKit自定义实现
  7. 依赖注入原理 php,PHP依赖注入原理与用法分析
  8. IncrediBuild 加速原理
  9. POJ 2798 2进制转换为16进制
  10. css布局-瀑布流的实现
  11. secsetupwizard以停止,三星手机恢复出厂设置之后,出现SecSetupWizard已停止的错误...
  12. Redis实用教程-----------菜鸟快速入门
  13. (转载)0201 0402 0603 0805 1206焊盘封装尺寸
  14. 什么是主数据,如何做好主数据管理?
  15. 谈谈 2020 年程序员收入报告
  16. 服务器系统开机黑屏只有个鼠标,Win7系统开机却显示黑屏并只有鼠标光标该怎么办...
  17. c# 微信公众号开发之token验证第三方服务器
  18. 前端实习生需要到达什么水平?
  19. python程序下载腾讯企业邮箱附件_python3使用腾讯企业邮箱发送邮件的实例
  20. Vue项目中应用天地图

热门文章

  1. 赋能数字经济发展的数字政府建设:内在逻辑与创新路径
  2. android有nfc功能吗,nfc功能是什么_哪些手机有nfc功能 - 全文
  3. orb-slam系列 LocalMapping线程 开始(八)
  4. matlab反演水温,HJ-1B/IRS热红外数据反演太湖水温的方法比较
  5. Linux内核驱动开发-USB热插拔信息调取
  6. 都不知道是不是resnet原始结构,keras实现....
  7. 单片机c语言彩灯依次点亮,基于单片机的LED彩灯控制器
  8. 企业数字化转型的驱动引擎—看中机云如何赋能企业,纵横云端|中机智库
  9. 【windows】TeamViewer软件连接不上网络
  10. 什么是Java Applet