利用Matlab自帶的深度學習工具進行車輛區域檢測與車型識別【福利-內附源碼與數據庫】(一)

前言

本此的博客詳細記錄了我使用Matlab進行車輛區域檢測(R-CNN)與車型識別(AlexNet)的過程。並且內包含了訓練數據集、測試數據集以及源碼。
訓練數據集是使用的斯坦福大學的一個車型數據庫,內含196種不同的車型。寫到這裏我真的很想吐槽一下這個數據庫裏面的奧迪車系:很多黑白的圖片啊喂!!! 做訓練的時候AlexNet數據輸入維度是3啊喂!!!害的我自己找了很多圖片啊!!!….

環境

測試環境:
硬件:
Intel i5-4590
GTX 980
軟件:
Matlab R2016b(只有這個版本才實現了RCNN…)

數據集的下載

嗯。一上來就發福利:
原始數據集,內含train/test:http://pan.baidu.com/s/1miTn9jy
我規整後的數據集,將圖片變換爲227*227,並且對少量黑白圖片進行了替換:http://pan.baidu.com/s/1pKIbQiB
接下來的這個是每一張圖片所對應的車型標註文件:http://pan.baidu.com/s/1nuOR7PR

在Matlab中下載AlexNet

AlexNet是2012年ImageNet大賽的冠軍。它一共有8層,其中了5個卷積層,2層全連接和一層分類,如果使用其對一張圖片進行前向傳播,那麼最後輸出的這張圖片屬於1000種物體中哪一個的概率。
我這裏對AlexNet在Matlab中進行了定義,這是我的代碼和網絡結構:

function [AlexLayer,opts]=MakeAlexLayer
inputLayer = imageInputLayer([227 227 3],'Name','Input');

middleLayers = [
convolution2dLayer([11 11], 96,'NumChannels',3,'Stride',4,'Name','conv1','Padding',0)
reluLayer('Name','relu1')
crossChannelNormalizationLayer(5,'Name','norm1')
maxPooling2dLayer(3, 'Stride', 2,'Name','pool1','Padding',0)

convolution2dLayer([5 5], 256, 'NumChannels',48,'Padding', 2,'Name','conv2','Stride',1)
reluLayer('Name','relu2')
crossChannelNormalizationLayer(5,'Name','norm2')
maxPooling2dLayer(3, 'Stride',2,'Name','pool2','Padding',0)

convolution2dLayer([3 3], 384, 'NumChannels',256,'Padding', 1,'Name','conv3','Stride',1)
reluLayer('Name','relu3')

convolution2dLayer([3 3], 384,'NumChannels',192, 'Padding', 1,'Name','conv4','Stride',1)
reluLayer('Name','relu4')

convolution2dLayer([3 3], 256, 'NumChannels',192,'Padding', 1,'Name','conv5','Stride',1)
reluLayer('Name','relu5')
maxPooling2dLayer(3, 'Stride',2,'Name','pool5','Padding',0)
];

finalLayers = [
fullyConnectedLayer(4096,'Name','fc6')
reluLayer('Name','relu6')
%caffe中有這一層
dropoutLayer(0.5,'Name','dropout6')

fullyConnectedLayer(4096,'Name','fc7')
reluLayer('Name','relu7')
%caffe中有這一層
dropoutLayer(0.5,'Name','dropout7')

%196種車
fullyConnectedLayer(196,'Name','fc8')
softmaxLayer('Name','softmax')
classificationLayer('Name','classification')
];

AlexLayer=[inputLayer
    middleLayers
    finalLayers];

opts = trainingOptions('sgdm', ...
    'Momentum', 0.9, ...
    'InitialLearnRate', 0.001, ...
    'LearnRateSchedule', 'piecewise', ...
    'MaxEpochs', 500, ...
    'MiniBatchSize', 100, ...
    'Verbose', true);
end

由於數據庫太小,loss一直比較高。所以我們還是在網上下載一下人家訓練好的網絡來微調吧(逃
地址:http://www.vlfeat.org/matconvnet/models/beta16/

對AlexNet進行Finetune

首先讀入這個AlexNet:

AlexNet=helperImportMatConvNet('AlexLayerFromWeb.mat');

觀察其網絡結構:

AlexNet.Layers

這裏寫圖片描述
我們要對其進行微調,那麼其實前面的卷積層都不用改,要改的就是最後的一個全連接層,要把它改成我們的層。由於車型一共是196種,所以全連接的輸出也得改成196,後面再接上一個softmax層和一個classificationLayer,並且定義訓練方式:

function [AlexLayer_New , optionsTransfer]=FineTune(AlexNet)
AlexNet_reduce = AlexNet.Layers(1:end-3);
%add
Last3Layers = [
fullyConnectedLayer(196,'Name','fc8','WeightLearnRateFactor',10, 'BiasLearnRateFactor',20)
softmaxLayer('Name','softmax')
classificationLayer('Name','classification')
];
AlexLayer_New=[AlexNet_reduce
    Last3Layers];

optionsTransfer = trainingOptions('sgdm',...
         'MaxEpochs',10,...
         'InitialLearnRate',0.0005,...
         'Verbose',true,'MiniBatchSize', 100);%MiniBatchSize根據顯卡內存而定
end

運行:

[AlexLayer_New , optionsTransfer]=FineTune(AlexNet)

得到新的網絡層級:
這裏寫圖片描述
Okay,現在我們要開始準備數據了。有兩個方式,可以直接下載我的traindata.mat,並且按照裏面的路徑來放一下cars_train這個文件夾。那麼我們就直接可以:

load('traindata.mat')

第二種方式,稍微複雜一點。打開我更改後的數據集,自己來做imageDatastore容器。首先解壓cars_train_croped(227_227)這個文件夾,然後在Matlab中寫入:

traindata=imageDatastore('cars_train_croped(227_227)/','LabelSource','none')

這裏寫圖片描述
這個時候是沒有Label的。我們的Label在哪裏呢?在cars_train_annos.mat中。將其讀入:

load 'cars_train_annos.mat';
%annotations.class即爲標註信息
traindata.Labels=categorical([annotations.class])

看看是否成功了:

unique(traindata.Labels)%應該輸出196個數字,從1-196

好的,現在我們可以開始訓練!

AlexNet_New=trainNetwork(traindata,AlexLayer_New,optionsTransfer)

這是我的結果:
這裏寫圖片描述
似乎還不錯。
調用其對圖片進行測試,我們需要讀入一個車型的文件:
這裏寫圖片描述
封裝一下進行測試的代碼:

function test(fileRoad,AlexNet_New,class_names)
testImage=imread(fileRoad);
testImage_=imresize(testImage,[227 227]);
TypeNum=classify(AlexNet_New,testImage_);
TypeName=class_names(TypeNum);
disp(TypeName);
figure;
imshow(testImage);
end

對單張圖片進行測試:

test('bmw.jpg',AlexNet_New,class_names)

結果:
這裏寫圖片描述
至於這張圖片具體型號是什麼,我也不知道。反正肯定是寶馬嘛。(廢話!)

—————————-UPDATE————————————-
新的demo已經開源:
http://blog.csdn.net/Mr_Curry/article/details/68921497

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章