基於深度學習的車輛檢測系統(MATLAB程式碼,含GUI介面)

思緒無限發表於2022-04-19
功能演示動圖

摘要:當前深度學習在目標檢測領域的影響日益顯著,本文主要基於深度學習的目標檢測演算法實現車輛檢測,為大家介紹如何利用\(\color{#4285f4}{M}\color{#ea4335}{A}\color{#fbbc05}{T}\color{#4285f4}{L}\color{#34a853}{A}\color{#ea4335}{B}\)設計一個車輛檢測系統的軟體,通過自行搭建YOLO網路並利用自定義的資料集進行訓練、驗證模型,最終實現系統可選取圖片視訊進行檢測、標註,以及結果的實時顯示和儲存。其中,GUI介面利用最新的MATLAB APP設計工具開發設計完成,演算法部分選擇時下實用的YOLO v2/v3網路,通過BDD100K資料集進行訓練、測試檢測器效果。本文提供專案所有涉及到的程式程式碼、資料集等檔案,完整資原始檔請轉至文末的下載連結,本博文目錄如下:

➷點選跳轉至文末所有涉及的完整程式碼檔案下載頁☇


完整資源下載連結https://mianbaoduo.com/o/bread/YZaal55t

介紹及演示視訊連結:https://www.bilibili.com/video/BV1oh411k7q7/(歡迎關注博主B站視訊)

程式碼使用介紹及演示視訊連結:https://www.bilibili.com/video/BV1No4y197rW/


前言

    如今機器視覺領域深度學習演算法已經大行其道,也讓人工智慧的實現不再那麼遙不可及,但是在目標檢測領域,讓計算機超越人類還需讓更多的人蔘與進來繼續努力。如今眾多的高校,甚至中小學已經將人工智慧納入了學習科目,這確實能讓人感受到AI的魅力以及社會對其重視程度。研究、學習及從事AI技術已近5年,博主自認為對其中的基本知識也算學到點皮毛,因此這裡開一個目標檢測專欄,根據自己的經驗提供點例項幫助大家入門了。

    印象中玩深度學習彷彿用的都是Python,但其實現在MATLAB也是可以的,並且玩得也不賴。由於高校幾乎普遍青睞MATLAB,恐怕很多人最熟悉的程式語言要屬它了。在網上查閱了很久,利用MATLAB實現的這類程式屬實不多,因此用它來寫一個Demo就有必要了。


1. 效果演示

    詳細介紹前還是先看看整體效果吧,畢竟質量不高的資源網上多得是,沒啥吸引力的恐怕大家看都不想看了。先上幾個動圖看看介面了,介面中預設裝載了博主訓練好的模型,選擇一張圖片可標記出目標並顯示標記框位置、識別型別及置信度值,GUI介面如下圖所示:

功能演示動圖

    識別出的圖片結果可通過顯示介面右上角上的選單欄選擇另存為圖片檔案,將帶有識別框的圖片儲存到自己的電腦上。另外介面可實現縮放、拖動等常見圖片處理功能,展示介面如下:

功能演示動圖

    選擇一個視訊格式的檔案可對視訊進行逐幀檢測,在視訊中標註出檢測結果顯示在介面上,最終檢測完成的視訊檔案預設儲存在當前資料夾下,該功能的展示介面如下:

功能演示動圖

    本專案所有功能在MATLAB R2020b中已測試通過,想要更多詳細展示資訊的朋友可以去博主的B站視訊中檢視,在下面的章節中將介紹如何實現以上展示的功能。


2. 車輛資料集

2.1 BDD 100k資料集

    車輛檢測的資料集目前有很多,常見的大型開源資料集當屬BDD 100K十分好用了,作為自動駕駛常用大型多樣化資料集,其標註超過100,000張影像,類別包含公共汽車,行人,自行車,卡車,小汽車,火車和騎手等,用於目標檢測、全幀分割等。該資料集的截圖如下:

功能演示動圖

    若要下載該資料集,可訪問它的官網地址下載,但官網國內的下載速度較慢,這裡已將其整理至百度網盤,需要下載的朋友也可通過博主的博文《深度學習常見資料集介紹與下載》獲取下載連結。下載後的檔案目錄如下:

功能演示動圖

    這個資料集確實很大(約10G),訓練的時間實在太長了,因此這個專案裡面不使用全部的資料,而是選擇其中的驗證集“bdd100k_val”資料夾下的檔案用於訓練。要使用全部資料集的朋友可將程式中的路徑修改為完整資料集資料夾。

    為了使得該資料集能夠方便用MATLAB處理,從原資料集的標註檔案“bdd100k_labels_images_val.json”檔案中抽取了小汽車的類別,並重新寫入到mat檔案中。篩選和處理部分圖片後,標註檔案的資訊包括圖片路徑和標註框的座標,其資料檔案的資訊如下:

功能演示動圖

2.2 自定義資料集

    若要使用自行定義的資料集可按照以上的格式進行處理,通過指令碼將標註檔案儲存為mat格式,如下圖所示為自定義的資料集的圖片檔案截圖和標註檔案:

功能演示動圖
功能演示動圖

    這兩個資料集都已放在資料夾中,後者只有幾百張圖片,因此對於想要學習和除錯程式碼的朋友會很方便。如果不是特別注重準確率,建議使用第二個資料集,在訓練和測試的時候速度會快很多,最後的結果其實也還可以,不妨一試。


3. 搭建並訓練網路

3.1 載入資料集

    首先載入準備好的資料集,檢視並顯示資料資訊。其次,對於圖片資料集需要為訓練器指定好每張圖片的絕對路徑,以方便讀取:

clear
clc

doTraining = true; % 是否進行訓練

% 解壓資料
% data = load('./data/carDatasetGroundTruth.mat');
% vehicleDataset = data.carDataset; % table型,包含檔案路徑和groundTruth
data = load('./data/vehicleDatasetGroundTruth.mat');
vehicleDataset = data.vehicleDataset; % table型,包含檔案路徑和groundTruth

% 新增絕對路徑至vehicleDataset中
vehicleDataset.imageFilename = fullfile([pwd, '/data/'],vehicleDataset.imageFilename);

% 顯示資料集中的一個影像,以瞭解它包含的影像的型別。
vehicleDataset(1:4,:) % 顯示部分資料情況

    以上程式碼首先載入了標註檔案,然後通過fullfile函式將當前資料夾位置新增到圖片路徑中,執行可以檢視到部分標註資訊如下:

ans =
  4×2 table
                                   imageFilename                                     vehicle   
    ___________________________________________________________________________    ____________
    {'E:\Works\code\VehicleDetection\train\data\vehicleImages\image_00001.jpg'}    {1×4 double}
    {'E:\Works\code\VehicleDetection\train\data\vehicleImages\image_00002.jpg'}    {1×4 double}
    {'E:\Works\code\VehicleDetection\train\data\vehicleImages\image_00003.jpg'}    {1×4 double}
    {'E:\Works\code\VehicleDetection\train\data\vehicleImages\image_00004.jpg'}    {1×4 double}

    將資料集分成兩部分:一個是用於訓練檢測器的訓練集,一個是用於評估檢測器的測試集,這裡選擇70%的資料進行訓練,其餘資料用於評估。該部分程式碼如下:

% 將資料集分成兩部分:一個是用於訓練檢測器的訓練集,一個是用於評估檢測器的測試集。
% 選擇70%的資料進行訓練,其餘資料用於評估。
rng(0); % 控制隨機數生成
shuffledIndices = randperm(height(vehicleDataset));
idx = floor(0.7 * length(shuffledIndices) );
trainingDataTbl = vehicleDataset(shuffledIndices(1:idx),:);
testDataTbl = vehicleDataset(shuffledIndices(idx+1:end),:);

    將劃分出的訓練和驗證資料集資料和標籤進行轉存,實現程式碼如下:

% 儲存資料和標籤
imdsTrain = imageDatastore(trainingDataTbl{:,'imageFilename'}); % 路徑
bldsTrain = boxLabelDatastore(trainingDataTbl(:,'vehicle')); % 真實框和類別

imdsTest = imageDatastore(testDataTbl{:,'imageFilename'});
bldsTest = boxLabelDatastore(testDataTbl(:,'vehicle'));

    聯合檔案路徑和真實框,整理訓練和測試集,這部分實現程式碼如下:

% 整理訓練測試集
trainingData = combine(imdsTrain,bldsTrain); % 聯合檔案路徑和真實框
testData = combine(imdsTest,bldsTest);

    為了幫助瞭解標註資訊的使用,可讀取trainingData中的圖片資料及真實框,通過insertShape函式在影像中進行標註並顯示:

% 顯示資料
data = read(trainingData); % data包括圖片資料、真實框座標、類別
I = data{1};
bbox = data{2};
annotatedImage = insertShape(I,'Rectangle',bbox); % 在資料矩陣中標出真實框
annotatedImage = imresize(annotatedImage,2);
figure
imshow(annotatedImage) % 顯示影像

顯示標註影像如下圖所示:

功能演示動圖

3.2 建立YOLO目標檢測器

    搭建YOLO v2目標檢測網路:YOLO v2由特徵提取網路和檢測網路兩個子網路組成。特徵提取網路通常是預訓練的CNN,這裡特徵提取網路使用的是ResNet-50,當然還可以使用其他經過預訓練的網路,例如MobileNet v2ResNet-18,一般根據應用場景和問題的複雜程度選擇合適的網路。與特徵提取網路相比,檢測網路是一個小的CNN,它由一些卷積層和YOLO v2特有的層組成。MATLAB中提供了yolov2Layers函式,其中給定了預訓練的ResNet-50特徵提取網路,可使用該功能自動建立YOLO v2物件檢測網路。

    yolov2Layers要求指定幾個輸入來引數化YOLO v2網路,詳細使用方法可參考其官方文件,其引數主要有:

  • 網路輸入大小
  • 錨框
  • 特徵提取網路

    在目標檢測中網路的輸入尺寸一定程度上會影響檢測結果,因此需要評估網路輸入大小和資料的類別數選定。在選擇網路輸入大小時,應先考慮網路本身所需的最小尺寸、訓練影像的大小以及在選定大小下處理資料所產生的計算量。一般情況下,傾向於選擇一個接近於訓練影像大小且大於網路所需輸入大小的網路輸入,這裡為了減少執行程式的計算成本,指定網路輸入大小為[224 224 3](執行網路所需的最小尺寸)。

% 建立yolo網路
inputSize = [448 448 3];
numClasses = width(vehicleDataset)-1; % 通過table的列數計算類別數

    開始訓練之前需要估算錨框,這要考慮影像的調整大小,調整訓練資料的大小以估計錨框。好在MATLAB中提供了estimateAnchorBoxes函式,根據訓練資料中物件的大小來估計錨框。根據transform函式預處理的訓練資料,然後確定錨框個數並估計錨框。使用內建的函式preprocessData將訓練影像資料調整為網路規定的輸入大小。

% 用於評估錨框個數
trainingDataForEstimation = transform(trainingData,@(data)preprocessData(data,inputSize));
numAnchors = 7;
[anchorBoxes, meanIoU] = estimateAnchorBoxes(trainingDataForEstimation, numAnchors)

輸出結果如下:

inputSize = [448 448 3];
anchorBoxes =
    14    10
    34    25
   226   176
   218   114
   124    75
   132   122
    65    53
meanIoU =
    0.6960

    設定特徵提取層網路為resnet50,選擇‘activation_40_relu’作為特徵提取層。該特徵提取層輸出的特徵圖經過16倍下采樣,這樣的下采樣量算是空間解析度與所提取特徵強度之間的一個折中,因為經過網路提取的特徵可能會在網路上顯示出更強的影像特徵。一般地,空間解析度的成本以及選擇最佳特徵提取層需要依據經驗分析。搭建網路的程式碼如下:

% 特徵提取層採用resnet50
featureExtractionNetwork = resnet50;

featureLayer = 'activation_40_relu';

% 設定yolo網路
lgraph = yolov2Layers(inputSize,numClasses,anchorBoxes,featureExtractionNetwork,featureLayer);

3.3 資料增強

    資料擴充通過在訓練過程中隨機轉換原始資料來提高網路訓練的準確性。通過使用資料增強,我們可以大大擴充訓練集的大小,而無需增加實際標記的訓練樣本的數量。可使用transform通過隨機水平翻轉影像和關聯的框標籤來增強訓練資料。值得注意的是,理想情況下測試和驗證資料應儘可能代表原始資料,未作修改的資料可以較好地評估模型,因此資料擴充不適用於測試和驗證資料。進行資料增強的程式碼如下:

% 進行資料增強
augmentedTrainingData = transform(trainingData,@augmentData);

% 視覺化增強後的圖片
augmentedData = cell(4,1);
for k = 1:4
    data = read(augmentedTrainingData);
    augmentedData{k} = insertShape(data{1},'Rectangle',data{2});
    reset(augmentedTrainingData);
end
figure
montage(augmentedData,'BorderSize',10)

視覺化增強後的圖片如下:

功能演示動圖

    預處理訓練資料:對增強後的訓練資料和驗證資料進行預處理,準備進行訓練。然後讀取預處理的訓練資料,這裡顯示一張處理後的影像並標註邊界框,幫助我們瞧一下餵給訓練器的是何方神聖:

% 對增強資料進行預處理
preprocessedTrainingData = transform(augmentedTrainingData,@(data)preprocessData(data,inputSize));

data = read(preprocessedTrainingData);

% 顯示一下
I = data{1};
bbox = data{2};
annotatedImage = insertShape(I,'Rectangle',bbox);
annotatedImage = imresize(annotatedImage,2);
figure
imshow(annotatedImage)

顯示影像如下:

功能演示動圖

3.4 訓練目標檢測網路

    訓練目標檢測器:這裡可以使用trainingOptions容器指定網路的訓練引數,設定‘ValidationData’作為預處理的驗證資料;設定‘CheckpointPath’為一個臨時位置,這樣能夠保證在訓練過程中及時儲存訓練的結果,如果培訓因電源中斷或系統故障而中斷,則可以從儲存的檢查點恢復訓練。訓練部分的程式碼如下:

% 訓練引數
options = trainingOptions('sgdm', ...
        'MiniBatchSize', 100, ....
        'InitialLearnRate',1e-3, ...
        'MaxEpochs',30,...
        'CheckpointPath', tempdir, ...
        'Shuffle','never');
    
if doTraining       
    % 訓練YOLOv2檢測器
    [detector,info] = trainYOLOv2ObjectDetector(preprocessedTrainingData,lgraph,options);
else
    % 載入預訓練模型
    pretrained = load('yolov2ResNet50.mat');
    detector = pretrained.detector;
end

    以上程式碼設定了doTraining決定是否執行訓練,當該值為true時開始進行訓練,反之則開始進行測試評估。接下來測試訓練好的模型並顯示測試結果:

% 測試訓練好的模型並顯示
I = imread(testDataTbl.imageFilename{4});
I = imresize(I,inputSize(1:2));
[bboxes,scores] = detect(detector,I);

I = insertObjectAnnotation(I,'rectangle',bboxes,scores);
figure
imshow(I)

顯示檢測結果如下:

功能演示動圖

3.5 評估網路效能

    利用測試集對檢測器進行評估:對於訓練好的目標檢測器有必要在大量影像上進行評估以測試其效能。MATLAB中的Computer Vision Toolbox提供了目標檢測器的評估功能,可以測量一些通用指標,例如平均精度(evaluateDetectionPrecision)和對數平均未命中率(evaluateDetectionMissRate)。在本專案中,我們使用平均精度來評估效能,平均精度中包含了檢測器做出正確分類的能力(精度)和檢測器找到所有相關目標的能力(召回率)。我們將測試資料進行和訓練資料相同的預處理操作,最終用來評估檢測器,這部分程式碼如下:

% 預處理測試集
preprocessedTestData = transform(testData,@(data)preprocessData(data,inputSize));
% 對測試集資料進行測試
detectionResults = detect(detector, preprocessedTestData);
% 評估準確率
[ap,recall,precision] = evaluateDetectionPrecision(detectionResults, preprocessedTestData);

figure
plot(recall,precision)
xlabel('Recall')
ylabel('Precision')
grid on
title(sprintf('Average Precision = %.2f',ap))

    精度/召回率(PR)曲線突出顯示了在不同召回水平下檢測器的精確度,最理想的情況是每處的精度均為1。要想提高平均精度,可以使用更多的訓練資料來提高訓練效果,但這也需要更多的訓練時間。這裡使用的是一個資料量較小的資料集,通過以上程式碼繪製的PR曲線如下圖所示:

功能演示動圖

    作為一個演示專案以上的平均精度還算可以了,可以提升的地方首當是訓練資料量了,因為只選取了一部分資料這使得模型的泛化效能不高,對於擬合效果也沒有作太多的優化,建議大家多做調整優化了。另外,前面程式碼中涉及到的呼叫函式這裡列出一下:。

% 影像預處理
function data = preprocessData(data,targetSize)
% 調整圖片和Bbox大小至targetSize
scale = targetSize(1:2)./size(data{1},[1 2]);
data{1} = imresize(data{1},targetSize(1:2));
% disp(data{2})
data{2} = bboxresize(data{2},scale);
end
% 影像增強
function B = augmentData(A)
% 應用隨機水平翻轉和隨機X/Y縮放影像;
% 如果重疊大於0.25,則在邊界外縮放的框將被裁減;
% 變換影像顏色
B = cell(size(A));

I = A{1};
sz = size(I);
if numel(sz)==3 && sz(3) == 3
    I = jitterColorHSV(I,...
        'Contrast',0.2,...
        'Hue',0,...
        'Saturation',0.1,...
        'Brightness',0.2);
end

% 隨機翻轉和縮放影像
tform = randomAffine2d('XReflection',true,'Scale',[1 1.1]);
rout = affineOutputView(sz,tform,'BoundsStyle','CenterOutput');
B{1} = imwarp(I,tform,'OutputView',rout);

% 對錨框進行相同的變換
[B{2},indices] = bboxwarp(A{2},tform,rout,'OverlapThreshold',0.25);
B{3} = A{3}(indices);

% 當框的資料不存在時返回原始資料
if isempty(indices)
    B = A;
end
end

下載連結

    若您想獲得博文中涉及的實現完整全部程式檔案(包括資料集,m, UI檔案等,如下圖),這裡已打包上傳至博主的麵包多平臺和CSDN下載資源。本資源已上傳至麵包多網站和CSDN下載資源頻道,可以點選以下連結獲取,已將所有涉及的檔案同時打包到裡面,點選即可執行,完整檔案截圖如下:

功能演示動圖

說明:本資源已經過除錯通過,下載後可通過MATLAB R2020b執行;另外本程式也通過打包APP應用檔案,可雙擊carDetector_UI.mlappinstall檔案匯入應用,可直接執行所有功能;因為涉及MATLAB部分內建功能,為保證完美執行,請使用MATLAB R2020b及以上版本執行。➷➷➷

完整資源下載連結1https://mianbaoduo.com/o/bread/YZaal55t

注:以上鍊接為博主的下載連結,CSDN下載資源頻道下載連結稍後上傳。博主最新發布的博文:實時車輛行人多目標檢測與跟蹤系統-上篇(UI介面清新版,Python程式碼)提供了車輛行人檢測與跟蹤的Python版本,介面與效果更加優良,歡迎嚐鮮!

程式碼使用介紹及演示視訊連結:https://www.bilibili.com/video/BV1No4y197rW/


結束語

    由於博主能力有限,博文中提及的方法即使經過試驗,也難免會有疏漏之處。希望您能熱心指出其中的錯誤,以便下次修改時能以一個更完美更嚴謹的樣子,呈現在大家面前。同時如果有更好的實現方法也請您不吝賜教。如果本博文反響較好,其介面部分也將在下篇博文中介紹,所有涉及的GUI介面程式也會作細緻講解,敬請期待!

相關文章