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文件的名稱與路徑。
到此數據集製作完成。