首先申明以下我使用的DeepLab caffe源码是原作者给出的:
https://bitbucket.org/aquariusjay/deeplab-public-ver2/overview
使用的model是:
http://liangchiehchen.com/projects/DeepLabv2_vgg.html
训练测试自己数据集时,我并没有套用原来的数据结构(就是外围的所有东西都不变,只是将voc数据集中的数据替换),而是修改了数据输层来将自己的数据送入网络.
本文中还会涉及到怎样进行一次测试并显示测试效果(mask图)
下面将从训练,测试,单张测试并显示效果三个部分进行阐述:
训练中主要需要修改的有三个部分:数据输入相关,run_pascal.sh文件修改,网络结构修改
我使用的数据输入层为我自己写的一个python类型的data层AerialImageDatasetLayer(其主要是参考FCN的数据读入层),这个层的作用是读取那些以文件夹为分类(而不是类似于poscal voc那样的将所有的images放一个文件夹,将所有的Segment放一个文件夹,然后通过train.txt,test.txt,val.txt这些txt文件夹来获取不同集合的数据),数据的存放形式如下:
dataset的根目录为dataset/BuildingDataset
训练样本images存放在: /dataset/BuildingDataset/train/images
训练样本GT存放在: /dataset/BuildingDataset/train/gt
测试样本images存放在: /dataset/BuildingDataset/val/images
测试样本GT存放在:/dataset/BuildingDataset/val/gt
你可以按照以上的方式存放你的数据集,然后在 https://github.com/NBJ2017/AerialImageDatasetLayer 上下载AerialImageDataset.py存放到与run_pascal.sh同样的目录即可.
接下来需要修改prototxt文件,prototxt文件也就是网络结构声明,存放在deeplab/exper/building/config/deeplab_largeFOV下,这里需要修改trian.prototxt 和 test.prototxt
将trian.prototxt中的data层改为:
layer {
name: "data"
type: "Python"
top: "data"
top: "label"
python_param {
module: "AerialImageDataset"
layer: "AerialImageDatasetLayer"
param_str: "{\'dataset_dir\': \'/home/irsa/deeplab/dataset/BuildingDataset\', \'seed\': 1337, \'split\': \'train\', \'mean\': (104.00699, 116.66877, 122.67892), \'batch\': 5}"
}
}
其中, dataset_dir为你的数据根目录, seed为随机数种子,split表示是用于干什么的数据,mean为数据集三个通道的平均数,batch为minibatch的大小.
将test.prototxt中的data层修改为:
layer {
name: "data"
type: "Python"
top: "data"
top: "label"
python_param {
module: "AerialImageDataset"
layer: "AerialImageDatasetLayer"
param_str: "{\'dataset_dir\': \'/home/irsa/deeplab/dataset/BuildingDataset\', \'seed\': 1337, \'split\': \'val\', \'mean\': (104.00699, 116.66877, 122.67892), \'random\': False, \'batch\': 1}"
}
}
主要修改:
(1)caffe编译目录:
#CAFFE_DIR=../deeplab-public-ver2
CAFFE_DIR=/home/irsa/deeplab
(2)task运行目录:
#EXP=.
EXP=/home/irsa/deeplab/exper/building
(3)类别数:
else
NUM_LABELS=2
echo "Wrong exp name"
将test.prototxt中的silence层改为:
代码段 小部件
注:silence层的作用是防止bottom指向的那个量不会因为没有使用而一直输出,如果想看以下没有silence层的效果,你可以吧silence层删了,就会在运行是发现输出一大堆的结果,这将浪费内存,减缓运行速度.
在终端中运行
cd deeplab/exper/building
sh run_pascal.sh 2>&1|tee trian.log
测试时就比较麻烦,主要是需要最后要以.mat格式输出segment结果,所以先要制作val_id.txt和val.txt文件并放在deeplab/exper/building/list目录下,生成方法如下:
在终端中输入python进入python命令行,然后依次输入以下命令
import os
images = list(os.listdir('/dataset/BuildingDataset/val/images'))
file = open(“val.txt”,'w')
file_id = open(“val_id.txt”,'w')
for m in images:
file.write(m+'\n')
file_id.write(m[0:-4]+'\n')
file.close()
file_id.close()
注:这里的'/dataset/BuildingDataset/val/images'你需要替换为自己数据集存放val数据images的目录.
因为还是要通过run_pascal.sh进行训练,所以还是需要修改以下这个文件:
将RUN_TRAIN=1
RUN_TEST=0
修改为:
RUN_TRAIN=0
RUN_TEST=1
然后在终端中运行
cd deeplab/exper/building
sh run_pascal.sh 2>&1|tee test.log
测试单张图像需要用到Input层,而DeepLab版本的caffe中没有这个层,所以你需要先添加input_layer(具体的添加方法网上有很多教程,这里不再赘述)
然后创建一个deploy.prototxt在deeplab/exper/building/config/deeplab_largeFOV下,这个文件相当于是将test_val.prototxt中的东西复制一份,然后将data层替换为:
layer {
name: "input"
type: "Input"
top: "data"
input_param {
# These dimensions are purely for sake of example;
# see infer.py for how to reshape the net to the given input size.
shape { dim: 1 dim: 3 dim: 505 dim: 505 }
}
}
然后删去silence层即可.
这个文件你也可以在https://github.com/NBJ2017/DeepLab-useOwnDateset直接下,但是并不建议,因为你这样下的肯定是用不了的,有兴趣你可以去看一下drop7_1的下一层命名方式,完全跟你的路径相关,而test_val.prototxt是由test.prototxt生成的,你会发现在test.prototxt中层的名称关系到你task存放的路径(我的路径是/home/irsa/deeplab/exper/building).
为了测试单张图像,并将分割的效果展示出来,我根据FCN中的infer.py函数改写了一个脚本(可以去
https://github.com/NBJ2017/DeepLab-useOwnDateset 下载),你可以修改
(1)你需要检测的图像目录:
image_path_name='/media/irsa/RRL/研二/fcn_building_segment/Level20/test.tif'
(2)需要检测的区域:
in_ = in_[500:1000,500:1000,:]
(3)net的设置:
net = caffe.Net('/home/irsa/deeplab/exper/building/config/deeplab_largeFOV/deploy.prototxt', '/home/irsa/deeplab/exper/building/model/deeplab_largeFOV/train_iter_20000.caffemodel', caffe.TEST)
然后运行就行了!