1. 前提
在配置SegNet网络之前,首先确保你电脑上已经成功配置过caffe框架,因为SegNe对cudnn版本的要求可能与你电脑配置的不一样,如果换成对应版本的话很麻烦,所以在在配置SegNet网络之前,确保你电脑上已经有成功配置了最原始的caffe,如果你电脑还没安装的话,可以参考这篇博客ubuntu16.04+anaconda2+gpu+caffe安装
2. 下载代码
- 首先下载SegNet要求的caffe代码:https://github.com/TimoSaemann/caffe-segnet-cudnn5 ,这个版本最好配置了,所以推荐这个。
- 下载SegNet网络模型文件:https://github.com/alexgkendall/SegNet-Tutorial ,里面有作者使用的数据集,和已经制作好的标签。在文章的最后我会介绍如何制作自己的数据集
- 下载网络权重模型:http://mi.eng.cam.ac.uk/~agk34/resources/SegNet/
3. 安装SegNe版本的caffe
-
解压下载下来的caffe-segnet-cudnn5-master.zip文件,重命名为caffe-segnet,进入caffe-segnet文件,输入命令
cp Makefile.config.example Makefile.config sudo Makefile.config
与安装caffe过程一模一样,可以参考前言推荐的博客,修改文件内容如下:
(1)应用 cudnn#USE_CUDNN := 1 #修改成: USE_CUDNN := 1
(2)应用 opencv 版本
#OPENCV_VERSION := 3 #修改为: OPENCV_VERSION := 3
(3)使用 python 接口
#WITH_PYTHON_LAYER := 1 #修改为 WITH_PYTHON_LAYER := 1
(4)修改 python 路径
在PYTHON_INCLUDE下面路径加一个local
PYTHON_INCLUDE := /usr/include/python2.7 \ /usr/local/lib/python2.7/dist-packages/numpy/core/include
(5)重要的一步
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib
修改为
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include /usr/include/hdf5/serial LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial
保存退出。
(6)在caffe-segnet文件夹下打双击打开Makefile文件#将: NVCCFLAGS +=-ccbin=$(CXX) -Xcompiler-fPIC $(COMMON_FLAGS) #替换为: NVCCFLAGS += -D_FORCE_INLINES -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS)
#将: LIBRARIES += glog gflags protobuf boost_system boost_filesystem m hdf5_hl hdf5 #改为: LIBRARIES += glog gflags protobuf boost_system boost_filesystem m hdf5_serial_hl hdf5_serial
(7)安装依赖
sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler sudo apt-get install --no-install-recommends libboost-all-dev sudo apt-get install libatlas-base-dev sudo apt-get install libgflags-dev libgoogle-glog-dev liblmdb-dev
-
开始编译caffe-segnet版本
输入命令make all -j8
如果你的电脑安装的cudnn版本和caffe-segnet版本要求不一致的话,必定会出现错误,在这里有一个小技巧,就是利用你电脑上已经配置好的caffe,把里面的cudnn相关文件拷过来就行,具体操作如下:
(1)打开caffe-master/include/caffe/util 文件夹,复制cudnn.hpp到caffe-segnet对应的文件夹下
(2)打开caffe-segnet/include/caffe/layers 文件夹,找到所有cudnn开头文件,如图所示,cudnn_conv_layer.hpp,一直到cudnn_tanh_layer.hpp
然后打开caffe-master/include/caffe/layers 文件夹,找到相对应的cudnn开头的文件,但是不要复制多余的,caffe-segnet有几个复制几个就行,将复制的cudnn开头的文件拷贝到caffe-segnet/include/caffe/layers 文件夹下,也就是替换到caffe-segnet原来的文件。
(3)caffe-master/src/caffe/util 文件夹,进行同样的操作,复制cudnn.cpp文件到caffe-segnet相同文件夹下
(4)打开caffe-segnet/src/caffe/layers 文件夹,与第(2)步进行同样的操作,就不在重复叙述了。 -
重新编译caffe-segnet版本
输入命令make clean make all -j8 sudo pycaffe -j8
当然在编译的时候可能依然会报错,但是这些错误在网上搜都是有对应的解决方案的,解决也很简单,就不在这叙述了。
当你成功编译之后,输入命令sudo gedit ~/.bashrc
注释掉你电脑上原来caffe的路径,添上caffe-segnet版本的cafe路径,一下是我的环境路径,我将caffe-segnet放在了SegNet文件夹下。export PYTHONPATH=/home/csm/SegNet/caffe-segnet/python:$PYTHONPATH
保存退出
source ~/.bashrc
测试一下python import caffe
如果没报错说明安装成功了。
4. 开始训练
-
解压下载的SegNet-Tutorial-master.zip文件,重命名为SegNet,就是存放caffe-segnet的文件夹,把它俩放在一起便于管理。
-
进入CamVid,你将会看到训练的图片以及对应标签,还有train.txt,test.txt文件,打开,修改对应的路径,如下图所示,也就是将相对路径改成绝对路径,避免在训练的时候会报错。
-
进入Models文件夹,打开segnet_solver.prototxt文件,修改对应的路径,以及参数,并在SegNet文件夹下,新建snapshot文件夹,用于存放训练生成的模型。
打开segnet_train.prototxt,修改路径。同时我也修改了batch_size大小。
-
开始训练
在SegNet文件夹下打开终端,输入#!bin/sh /home/csm/SegNet/caffe-segnet/build/tools/caffe train -gpu 0 -solver /home/csm/SegNet/Models/segnet_solver.prototxt
注意你自己电脑的路径名称。
-
开始测试
进入Models文件夹,打开segnet_inference.prototxt,修改你测试数据集的路径,然后在SegNet文件夹下创建Inference文件夹
输入命令,注意你电脑的路径``` python /home/csm/SegNet/Scripts/compute_bn_statistics.py /home/csm/SegNet/Models/segnet_train.prototxt /home/csm/SegNet/snapshot/_iter_64000.caffemodel /home/csm/SegNet/Inference/ ```
-
显示测试结果
python /home/csm/SegNet/Scripts/test_segmentation_camvid.py --model /home/csm/SegNet/Models/segnet_inference.prototxt --weights /home/csm/SegNet/Inference/test_weights.caffemodel --iter 233
到此所有训练过程结束了
5. 制作自己的数据集
-
制作label
可以参看这篇博客:https://blog.csdn.net/weixin_43122521/article/details/82558346 ,写的很详细,但是只是适合制作他的数据集,所以我在这稍微的添加一些内容。
网上有很多说制作标签用labelme软件,我以前也试过,但是会出现一点问题,所以就使用了PS,我觉得挺好使的。参考这篇博客https://blog.csdn.net/weixin_42795611/article/details/84073879 ,先仿照voc数据集,将标签标为如下颜色,有几种类别就标几种颜色就行。然后保存为png格式这时的标签为24位彩色图。类别名称 R G B background 0 0 0 背景 aeroplane 128 0 0 飞机 bicycle 0 128 0 bird 128 128 0 boat 0 0 128 bottle 128 0 128 瓶子 bus 0 128 128 大巴 car 128 128 128 cat 64 0 0 猫 chair 192 0 0 cow 64 128 0 diningtable 192 128 0 餐桌 dog 64 0 128 horse 192 0 128 motorbike 64 128 128 person 192 128 128 pottedplant 0 64 0 盆栽 sheep 128 64 0 sofa 0 192 0 train 128 192 0 tvmonitor 0 64 128 显示器
-
将原图与24位彩色标签图统一大小480x360
因为segnet网络要求图片为480x360,matlab代码如下:``` addpath('dealImg'); addpath('Img'); ListName=dir('Img\*.jpg'); [Pm,Pn]=size(ListName); for iPm=1:1:Pm %读取文件夹所有图片循环 oriImg=imread(ListName(iPm).name); readImg cutImg=imresize(oriImg,[360,480]); iDealName=ListName(iPm).name; iDealAddress='dealImg\'; iDealAll=strcat(iDealAddress,iDealName); ID=imresize(cutImg,1); imwrite(ID,iDealAll); end ```
-
将24为彩色标签图变为8位灰色图
python代码如下:``` from PIL import Image import numpy as np import os.path import glob def convert_gray(pngfile): img=Image.open(pngfile).convert('L') img.save(os.path.join('8bit', os.path.basename(pngfile)),'png') for pngfile in glob.glob('24bit/*'): convert_gray(pngfile) ```
-
因为segnet的数据集,像素0为背景,像素1,2,3……为目标,所以要对8为灰色图重新上色。
首先用matlab,imread函数读取图片,会显示你每个类别对应的灰度值,若果是安装我上面所说的办法制作标签的话,每个类别的像素值是一样的,你只要观察几张图的灰度值就行。
然后使用python代码进行上色。# -*- coding:UTF-8 -*- from PIL import Image from pylab import * import numpy import glob import os.path def convert(pngfile): im = array(Image.open(pngfile)) w = im.shape[0] h = im.shape[1] for x in range(w): for y in range(h): if im[x][y]==38: im[x][y]=1 elif im[x][y]==75: im[x][y]=2 elif im[x][y]==113: im[x][y]=3 elif im[x][y]==14: im[x][y]=4 elif im[x][y]==52: im[x][y]=5 else: im[x][y] = 0 img = Image.fromarray(im.astype('uint8')) img.save(os.path.join('label', os.path.basename(pngfile)), 'png') for pngfile in glob.glob('8bit/*'): convert(pngfile)
最后别忘了修改SegNet/CamVid文件夹下的train.txt和test.txt文件的名称与路径。
到此数据集制作完成。