转载自:http://blog.csdn.net/gavin__zhou/article/details/52142696
原理我已经在上篇博客说过,大家可以参考FCN原理篇
FCN有官方的代码,具体地址是FCN官方代码 不过我用的不是这个代码,我用的是别人修改官方的版本的代码,使用Chainer框架实现的,Chainer的源码链接: Chainer框架源码,如果大家使用过Keras的话,应该对它不会感到特别的陌生,Chainer: a neural network framework
好了,我使用的代码是FCN的Chainer implementation, 具体地址是FCN Chainer implementation
安装很简单,直接pip或者源码安装都可以,但是我在我的机器上装过几次,发现使用pip的方式最后fcn.data_dir这个变量的值会指向到你系统的Python下的dist-packages这个目录,但是这个目录需要root权限,所以不推荐使用pip直接安装的方式; 关于此问题的说明见: fcn.data_dir的问题
所以我最后使用的是源码安装的方式,这里推荐使用virtualenv工具建立虚拟环境,实践中发现这是最不会出错的方式,推荐使用!
Git clone https://github.com/wkentaro/fcn.git –recursive
sudo pip install virtualenv #安装virtualenv 创建虚拟目录 virtualenv test-fcn cd test-fcn 激活虚拟环境 source ./bin/activate 克隆fcn代码 git clone https://github.com/wkentaro/fcn.git –recursive cd fcn 安装fcn python setup.py develop
下载VOC2012数据集,放入fcn-data-pascal-VOC2012路径下 1. 转换caffe model为Chainer model ./scripts/caffe_to_chainermodel.py 2. load model,进行分割 ./scripts/fcn_forward.py –img-files data/pascal/VOC2012/JPEGImages/2007_000129.jpg
这个前后搞了快一个月,才把最终的训练搞定,其中艰辛很多,在这里写出来供大家参考
数据集做成VOC2012的segementClass的样子,下图是示例,上面一张是原图,下面一张是分割图
但是每一种label指定的物体都有对应的具体的颜色,这个我们犯了很多错,最后跟踪代码找出来的,具体的每一类的RGB值如下:
Index RGB值 0 (0,0,0) 1 (0,128,0) 2 (128,128,0) 3 (0,0,128) 4 (128,0,128) 5 (0,128,128) 6 (128,128,128) 7 (64,0,0) 8 (192,0,0) 9 (62,128,0) 10 (192,128,0这里只列出10类的值,更多类的可以看下面这段代码:
def bitget(byteval, idx): return ((byteval & (1 << idx)) != 0) def labelcolormap(N=256): cmap = np.zeros((N, 3)) #N是类别数目 for i in xrange(0, N): id = i r, g, b = 0, 0, 0 for j in xrange(0, 8): r = np.bitwise_or(r, (bitget(id, 0) << 7-j)) g = np.bitwise_or(g, (bitget(id, 1) << 7-j)) b = np.bitwise_or(b, (bitget(id, 2) << 7-j)) id = (id >> 3) cmap[i, 0] = r cmap[i, 1] = g cmap[i, 2] = b cmap = cmap.astype(np.float32) / 255 #获得Cmap的RGB值 return cmap def _label_rgb_to_32sc1(self, label_rgb): assert label_rgb.dtype == np.uint8 label = np.zeros(label_rgb.shape[:2], dtype=np.int32) label.fill(-1) cmap = fcn.util.labelcolormap(len(self.target_names)) cmap = (cmap * 255).astype(np.uint8) #转换为整数值 for l, rgb in enumerate(cmap): mask = np.all(label_rgb == rgb, axis=-1) label[mask] = l return label 123456789101112131415161718192021222324252627282930 123456789101112131415161718192021222324252627282930按照此颜色表做图就没有问题,代码可以正确的读取分割的ground-truth结果 原始的图像放在fcn/data/pascal/VOC2012/JPEGImages 分割的图像放在fcn/data/pascal/VOC2012/SegmentationClass 之后在fcn/data/pascal/VOC2012/ImageSets/Segmentation写train.txt,trainval.txt,val.txt,写入需要进行相应任务的图片的编号
./scripts/fcn_train.py
其会在fcn/data/ 下创建一个目录叫做SegmentationClassDataset_db,里面存放训练的图片的pickle数据,如果需要修改原始的训练图片则需要将此目录删除,否则默认读取此目录内的pickle数据作为图像的原始数据
会在fcn下创建snapshot这个目录,里面有训练保存的model,日志文件等,重新训练的话,建议删除此目录
./scripts/fcn_forward.py -c path/to/your/model -i path/to/your/image 结果存放在fcn/data/forward_out下