FCN从制作自己的数据集,到训练,测试中间感谢很多朋友的帮助!现在整理出来,希望能帮助到更多的人。以voc_fcn8s为例,详细说明一下整个过程。
按照voc的数据格式,分为benchmark和VOC2011,benchmark为训练集:VOC2011为测试集,benchmarck在 fcn.berkeleyvision.org/data/sbdd
VOC2011在 fcn.berkeleyvision.org/data/pascal
训练集的原图为.jpg/.png,标签为.mat. 测试集的原图和标签图都是.png/.jpg。这一点,从voc_layer.py中的读取数据的方式可以看出,VOCSegDataLayer()是读取测试集的方法,SBDDSegDataLayer()是读取训练集的方法。为了简单,我们在制作数据集的时候,我们将训练图片和测试图片都准备成图片形式,标签也是索引图。
假如我有两类,背景为0,目标为1,标签图就是单通道的灰度图。其中,背景的灰度值为0,目标的灰度值为1(从0开始,背景为0,连续的灰度值)这样制作完之后,标签图看起来是全黑(8位深),接下来,再将标签图制成索引图,至于什么是索引图,简单来说,就是做了一个map的映射,比如,将我前面设置的灰度值为0的背景,映射成一个自己设置的新的颜色(r,g,b),将灰度值为1的,映射成一个新的颜色(r,g,b)。索引图形式的label是P格式的,有新颜色的,此时的位深就等于制作索引图事对应了几个颜色,比如我的对应了0,1,此时的位深是1,如果对应了0,1,2,3,4,此时的位深是4。下面的这段代码可以帮助你查看图片的信息,如果输出[0,1]说明制作正确。
import PIL
from PIL import Image
import numpy as np
image = PIL.Image.open('.....图片路径')
print(np.unique(image))
将灰度图转成索引图的代码如下:
# -*- coding: utf-8 -*-
__author__ = 'cheese'
from random import randint
from PIL import Image
import os
'''
根据灰度图的值制作索引图
'''
path = "C:\\Users\\Administrator\\Desktop\\Tarim20\\indexplan\\"
os.chdir(path)
imgList = os.listdir(path)
for pic in imgList:
img = Image.open(pic)
img.putpalette([0,0,0,255,0,0]) #灰度值为0的改为(0,0,0),灰度值为1的改为(255,0,0),按顺序来,这个长度决定了位深
img.save(pic)
print ("done!")
sbdd/benchmark/benchmark_RELEASE/dataset/img下面放训练原图,cls下面放索引图,train.txt里面逐行写入训练图片名,注意不带后缀:
1511664041284
1511664333882
1511664361617
1511666437817
1511666511922
1511666520225
1511666741161
1511666868122
1511666942753
1511666950786
pascal/VOC2011/JPEGImages下面放验证原图,SegmentationClass下面放索引图
segvalid11.txt在/data/pascal/VOC2011/ImageSets/Segmentation/下,原本的是val.txt,复制一份产生segvalid11.txt.里面写验证集的文件名,注意不带后缀
solve.py和val.txt中都指向这个文件。
cls中本来应该存放.mat文件,我们放入的是索引图,需要修改读取数据的代码,仿照voc_layer.py中VOCSegDataLayer类中读取label的方法,我们将SBDDSegDataLayer读取label的方法改为读取.png格式的:
def load_label(self, idx):
"""
Load label image as 1 x height x width integer array of label indices.
The leading singleton dimension is required by the loss.
"""
# import scipy.io
# mat = scipy.io.loadmat('{}/cls/{}.mat'.format(self.sbdd_dir, idx))
# label = mat['GTcls'][0]['Segmentation'][0].astype(np.uint8)
# label = label[np.newaxis, ...]
# return label
im = Image.open('{}/cls/{}.png'.format(self.sbdd_dir, idx))
label = np.array(im, dtype=np.uint8)
label = label[np.newaxis, ...]
return label
修改:
1.solver.prototxt中的一些超参数的设置
2.train.prototxt/val.prototxt :
a:修改读取文件路径
b: 因为我改变了最终输出的类别,本来以为将最后的输出类别改成2即可,但是发现会报错,因为fcn的反卷积层固定了输入和输出大小一致。这样,就不得不从后往前把所有的21都改掉,我但同时又想使用fcn8s-heavy-pascal.caffemodel预训练模型,不想修改那么多shape,所以在最后一个反卷积层之后加一个num_output:2 的卷积层。我这里就不需要修改solve.py中copy_form函数,因为与训练模型的参数有的我的网络结构全都有,不存在强行复制的情况,这里说一下,copy_form和transplant的区别:
copy_from:
transplant:
如果训练fcn-16s,则可以直接copy_from自己的fcn-32s的model的权重,不需要transplant
如果训练fcn-8s,则可以直接copy_from自己的fcn-16s的model的权重,不需要transplant
如果是用vgg-16的与训练模型来训练fcn-32s,需要transplant(因为vgg-16中fc6,fc7的网络结构和fcn中fc6,fc7的网络结构不同,直接copy_from便会报错)
layer {
name: "upscore8"
type: "Deconvolution"
bottom: "fuse_pool3"
top: "upscore8"
param {
lr_mult: 0
}
convolution_param {
num_output: 21
bias_term: false
kernel_size: 16
stride: 8
}
}
layer {
name: "end2"
type: "Convolution"
bottom: "upscore8"
top: "end2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output:5
pad: 0
kernel_size: 1
}
}
layer {
name: "score"
type: "Crop"
bottom: "end2" #"upscore8"
bottom: "data"
top: "score"
crop_param {
axis: 2
offset: 31
}
}
在voc-fcn8s下面输入:
python solve.py
即可开始训练。
如果报错IndexError: list index out of range*
执行python solve.py 0
即可
训练的时候,初始的loss很高,但是不用预训练模型的话,loss会收敛的很慢,
单张测试:
1.修改deploy.prototxt [这里面参考train.prototxt,添加了一个卷积层]
修改voc-fcn8s/infer.py:
1.传入训练好的模型路径和deploy.prototxt
# load net
net = caffe.Net('/new/wc/FCN/fcn.berkeleyvision.org/voc-fcn8s/deploy.prototxt',
'/new/wc/FCN/fcn.berkeleyvision.org/voc-fcn8s/snapshot/train/_iter_1000.caffemodel', caffe.TEST)
2.将索引图对应回彩图,可以在后面加上这段代码:
palette=[]
for i in range(256):
palette.extend((i,i,i))
#将预测出的第一类,对应回[0,0,0],将预测出的第二类,对应回[255,0,0]
palette[:3*2]=np.array([[0, 0, 0],
[255,0,0],], dtype='uint8').flatten()
im.putpalette(palette)
im.show()
#保存结果
im.save('/new/wc/FCN/fcn.berkeleyvision.org/voc-fcn8s/testpic/res/'+imgName)