本文主要介紹如何使用?YOLOv4 目標(biāo)檢測模型和 Darknet 框架來創(chuàng)建一個路面坑洞檢測系統(tǒng)。
背景介紹
高速行駛時,道路上的坑洼會變得非常危險。當(dāng)汽車或車輛的駕駛員無法從遠(yuǎn)處看到坑洼并及時剎車或?qū)⑵嚳焖亳傠x時,情況更是如此。后面的動作對其他司機也同樣危險。但是,如果我們使用深度學(xué)習(xí)和目標(biāo)檢測來檢測前方遠(yuǎn)處的坑洼呢?這樣的系統(tǒng)一定會對我們有所幫助。這正是我們將在本文中所做的。我們將使用YOLOv4 目標(biāo)檢測模型和 Darknet 框架來創(chuàng)建一個路面坑洞檢測系統(tǒng)。
Darknet與YOLOv4簡介
Darknet 項目是一個開源對象檢測框架,以為 YOLO 模型提供訓(xùn)練和推理支持而聞名。該庫是用 C 編寫的。
Darknet項目由Joseph Redmon于 2014年啟動,并發(fā)布了第一個 YOLO 論文。YOLOv3 發(fā)布后不久,它被Alexey Bochkovskiy 接管,他現(xiàn)在維護著原始存儲庫的一個活躍分支。他還增加了對YOLO?v4模型的支持。?
YOLOv4、YOLOv4-Tiny 和 YOLOv4-CSP 是存儲庫中一些眾所周知且廣泛使用的對象檢測模型。除了這些,Alexey 還在代碼庫中添加了一些非常好的特性:
該代碼現(xiàn)在支持對具有 Tensor 核心的 GPU 進行混合精度訓(xùn)練。它可以在支持它的 GPU 上將訓(xùn)練速度提高約 3 倍。
在訓(xùn)練期間還添加了馬賽克增強,這極大地提高了模型的準(zhǔn)確性,因為它學(xué)會了在更困難的圖像中檢測對象(有關(guān)詳細(xì)信息,請參閱第3.3節(jié)。YOLOv4 論文的其他改進)。
該代碼現(xiàn)在還支持多分辨率訓(xùn)練。這會在訓(xùn)練模型時每 10 個批次將圖像的分辨率更改為基本分辨率的 +-50%。這有助于模型學(xué)習(xí)檢測更小和更大圖像中的對象。但與單分辨率訓(xùn)練相比,它也需要大量的 GPU 內(nèi)存來訓(xùn)練相同的批量大小。這樣做的原因是,當(dāng)分辨率更改為基本分辨率的 +50% 時,每隔幾批,就會需要更多的 GPU 內(nèi)存。
坑洞數(shù)據(jù)集
本文中,我們將結(jié)合兩個開源數(shù)據(jù)集來獲得一組規(guī)模適中且變化多樣的圖像,用于訓(xùn)練 YOLOv4 模型。
我們從Roboflow(https://public.roboflow.com/object-detection/pothole/1)獲得其中一個數(shù)據(jù)集。該數(shù)據(jù)集總共包含 665 張圖像,并且已經(jīng)分為 465 張訓(xùn)練圖像、133 張驗證圖像和 67 張測試圖像。
我們使用的另一個數(shù)據(jù)集在這篇ResearchGate 文章(https://www.researchgate.net/publication/282807920_Dataset_of_images_used_for_pothole_detection)中提到。盡管作者提供了指向大型數(shù)據(jù)集的鏈接,但我們出于我們的目的使用了其中的一個子集。
我們以隨機方式組合這兩個數(shù)據(jù)集,并創(chuàng)建一個訓(xùn)練、驗證和測試集。數(shù)據(jù)集只包含一個類,即 Pothole。
您無需擔(dān)心數(shù)據(jù)集處理的這一階段,因為您將直接訪問最終數(shù)據(jù)集。
我們將只對數(shù)據(jù)集進行一個小的預(yù)處理,我們將在代碼部分討論其細(xì)節(jié)。
我們將在此處使用的數(shù)據(jù)集具有以下拆分:1265 個訓(xùn)練圖像、401 個驗證圖像和 118 個驗證圖像。
訓(xùn)練YOLOv4模型
從這里開始,我們將討論這篇文章的編碼細(xì)節(jié)。這包括為圖像路徑生成文本文件的預(yù)處理步驟、配置文件的準(zhǔn)備、數(shù)據(jù)文件的創(chuàng)建、訓(xùn)練和對測試集的評估。
有兩種方法可以在這里進行。我們可以繼續(xù)應(yīng)該在本地系統(tǒng)的終端和 IDE 上執(zhí)行的步驟,或者應(yīng)該在 Jupyter 筆記本(可能是本地、Colab 或任何其他基于云的 Jupyter 環(huán)境)中執(zhí)行的步驟。Jupyter notebook 以及所有實現(xiàn)細(xì)節(jié)已經(jīng)可供下載。在這里,我們按照在 IDE 中開發(fā)代碼和在終端中執(zhí)行命令的步驟進行操作。這樣,我們將獲得兩者的經(jīng)驗。如果您使用的是 Windows 操作系統(tǒng),建議您使用提供的 Jupyter notebook 并在 Colab 上運行它。以下本地執(zhí)行步驟是在 Ubuntu 系統(tǒng)上執(zhí)行的。盡管請注意,如果您在本地系統(tǒng)上繼續(xù)進行,一些實驗將需要超過 10 GB 的 GPU 內(nèi)存。?
【1】下載數(shù)據(jù)集
要下載數(shù)據(jù)集,只需在您選擇的目錄中的終端中執(zhí)行以下命令。
wget https://learnopencv.s3.us-west-2.amazonaws.com/pothole-dataset.zip
并使用以下命令提取數(shù)據(jù)集。
unzip pothole-dataset.zip
在數(shù)據(jù)集目錄中,您應(yīng)該找到以下目錄結(jié)構(gòu):
train、valid 和 test 目錄包含圖像以及包含標(biāo)簽的文本文件。對于 YOLOv4,邊界框坐標(biāo)需要是相對于圖像大小的 [x_center, y_center, width, height] 格式。除此之外,每種情況下的標(biāo)簽都是 0,因為我們只有一個類。下一個塊顯示了一個這樣的文本文件的示例。
文本文件中的每一行代表數(shù)據(jù)集中的一個對象。第一個數(shù)字是 0,代表類別。其余四個浮點數(shù)表示上述格式的坐標(biāo)。
【2】克隆和構(gòu)建Darknet
克隆并構(gòu)建Darknet(https://github.com/AlexeyAB/darknet)。在終端中執(zhí)行以下命令。
git clone https://github.com/AlexeyAB/darknet.git
使用以下命令進入暗網(wǎng)目錄:
cd darknet
請注意,所有剩余的命令都將從Darknet目錄執(zhí)行。因此,所有路徑都將相對于該目錄,并且數(shù)據(jù)集目錄應(yīng)該是相對于Darknet目錄的一個文件夾。
現(xiàn)在,我們需要構(gòu)建Darknet。我們在此處遵循的構(gòu)建過程期望 GPU 與安裝的 CUDA 和 cuDNN 一起在系統(tǒng)中可用。打開 Makefile 并在前 7 行中進行以下更改:
現(xiàn)在,保存文件并在終端中運行 make
make
在構(gòu)建 Darknet 時,如果遇到以下錯誤:
opencv.hpp: No such file or directory
然后您需要使用以下命令安裝 OpenCV,然后再次運行 make。
apt?install?libopencv-dev
現(xiàn)在準(zhǔn)備在我們的本地系統(tǒng)上使用支持 CUDA (GPU) 的 Darknet。
【3】為圖像路徑準(zhǔn)備文本文件
對于 Darknet YOLOv4 訓(xùn)練和測試,我們需要將所有圖像路徑保存在文本文件中。然后這些文本文件將用于映射到圖像路徑。
注意:文本文件中的路徑應(yīng)該是相對于暗網(wǎng)目錄的。
讓我們看一下代碼,這將使事情變得更清晰。prepare_darknet_image_txt_paths.py 包含用于生成 train.txt、valid.txt 和 test.txt 文件的代碼:
import os
DATA_ROOT_TRAIN = os.path.join( '..', 'dataset', 'train' ) DATA_ROOT_VALID = os.path.join( '..', 'dataset', 'valid' ) DATA_ROOT_TEST = os.path.join( '..', 'dataset', 'test' ) train_image_files_names = os.listdir(os.path.join(DATA_ROOT_TRAIN)) with open('train.txt', 'w') as f: for file_name in train_image_files_names: if not '.txt' in file_name: write_name = os.path.join(DATA_ROOT_TRAIN, file_name) f.writelines(write_name+' ') valid_data_files__names = os.listdir(os.path.join(DATA_ROOT_VALID)) with open('valid.txt', 'w') as f: for file_name in valid_data_files__names: if not '.txt' in file_name: write_name = os.path.join(DATA_ROOT_VALID, file_name) f.writelines(write_name+' ') test_data_files__names = os.listdir(os.path.join(DATA_ROOT_TEST)) with open('test.txt', 'w') as f: for file_name in test_data_files__names: if not '.txt' in file_name: write_name = os.path.join(DATA_ROOT_TEST, file_name) f.writelines(write_name+' ')
我們只需遍歷包含圖像文件的 train、valid 和 test 目錄并創(chuàng)建文本文件。文本文件將在暗網(wǎng)目錄中創(chuàng)建。
以下是 train.txt 文件中的幾行:
這里有兩點需要注意:
文件的順序已經(jīng)隨機化。
并且圖像路徑是相對于當(dāng)前目錄的。
我們都準(zhǔn)備好數(shù)據(jù)集準(zhǔn)備部分并構(gòu)建Darknet?,F(xiàn)在,讓我們進入核心實驗部分,即使用不同參數(shù)訓(xùn)練 YOLOv4 模型。
【4】訓(xùn)練具有固定分辨率的 YOLOv4-Tiny 模型
我們將從訓(xùn)練 YOLOv4-Tiny 模型開始。我們將為此創(chuàng)建配置和數(shù)據(jù)文件。對于配置,我們將更改要訓(xùn)練的批次大小和批次數(shù),但將其他設(shè)置保留為默認(rèn)值。
設(shè)置模型配置和數(shù)據(jù)文件
在 darknet 文件夾的 cfg 目錄中,創(chuàng)建 yolov4-tiny-custom.cfg 文件的副本。將其命名為 yolov4-tiny-pothole.cfg。從這里開始,我們討論的所有配置設(shè)置都基于 Colab 上可用的 16GB Tesla P100 GPU。您可以根據(jù)自己的可用性調(diào)整配置,但我們在這里討論的實驗和結(jié)果是基于上述硬件的設(shè)置。
在新的配置文件中,將批次從 64 更改為 32,將 max_batches 設(shè)置為8000,步驟為6400、7200?;旧?,我們將訓(xùn)練模型進行 8000 步,批量大小為 32。學(xué)習(xí)率將計劃在 6400 和 7200 步降低。接下來是過濾器和類的數(shù)量。在微型模型配置文件中,我們可以找到兩個 [yolo] 層。將這些層中的類從 80 更改為 1,因為我們只有一個類。在每個 [yolo] 層之前,都會有包含過濾器參數(shù)的 [convolutional] 層。將過濾器的數(shù)量更改為(num_classes+5)*3給出的值,即18在我們的例子中。而對于微型 YOLOv4 模型,我們需要在 [yolo] 層之前的兩個 [convolutional] 層中進行更改。
然后我們需要在 build/darknet/x64/data 中創(chuàng)建一個 pothole.names 文件。這將包含每個新行中的類名。由于我們只有一個班級,因此只需在第一行輸入單詞 pothole。
接下來,我們需要創(chuàng)建一個 .data 文件。我們?yōu)槊總€實驗創(chuàng)建一個單獨的文件。在 build/darknet/x64/data 中創(chuàng)建一個 pothole_yolov4_tiny.data。該文件將包含有關(guān)類、數(shù)據(jù)集路徑和存儲訓(xùn)練模型的位置的信息。在該文件中輸入以下信息:
classes = 1 train = train.txt valid = valid.txt names = build/darknet/x64/data/pothole.names backup = backup_yolov4_tiny
我們指定類的數(shù)量、訓(xùn)練和驗證文本文件路徑、類名稱的路徑和備份文件夾路徑。這是保存訓(xùn)練模型的文件夾。雖然我們可以為所有實驗使用同一個文件夾,但我們將為每個實驗創(chuàng)建一個新文件夾。
在我們繼續(xù)之前,請確保在將保存訓(xùn)練模型的暗網(wǎng)目錄中創(chuàng)建 backup_yolov4_tiny 文件夾。否則,訓(xùn)練過程將拋出錯誤,因為目錄不是自動創(chuàng)建的。
這樣就完成了我們在開始訓(xùn)練之前需要完成的所有步驟。對于進一步的實驗,這將變得更容易,因為我們已經(jīng)為第一個實驗準(zhǔn)備了所有配置。
為了訓(xùn)練模型,我們將使用已經(jīng)可用的預(yù)訓(xùn)練微型模型。通過在終端上執(zhí)行以下命令來下載它:
wget https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.conv.29
然后在darknet目錄內(nèi)的終端中執(zhí)行以下命令:
./darknet detector train build/darknet/x64/data/pothole_yolov4_tiny.data cfg/yolov4-tiny-pothole.cfg yolov4-tiny.conv.2
? ?訓(xùn)練將需要一些時間,具體取決于所使用的硬件。訓(xùn)練結(jié)束時,您應(yīng)該得到類似于以下內(nèi)容的輸出:
Saving weights to backup_yolov4_tiny/yolov4-tiny-pothole_8000.weights Saving weights to backup_yolov4_tiny/yolov4-tiny-pothole_last.weights Saving weights to backup_yolov4_tiny/yolov4-tiny-pothole_final.weights If you want to train from the beginning, then use flag in the end of training command: -clear
下圖顯示了整個訓(xùn)練過程中的損失圖:
在訓(xùn)練結(jié)束時,具有 416×416 固定分辨率的 YOLOv4-Tiny 的損失約為 0.12。對于目標(biāo)檢測訓(xùn)練,這看起來足夠低。但我們將從mAP(平均平均精度)中真正了解它的準(zhǔn)確性。
我們將需要另一個 .data 文件來提供測試圖像文件的路徑。使用以下內(nèi)容在 build/darknet/x64/data 目錄中創(chuàng)建 pothole_test.data。
classes = 1 train = train.txt valid = test.txt names = build/darknet/x64/data/pothole.names backup = backup_test/
這里唯一改變的是有效文本文件的路徑和備份文件夾名稱。我們也可以使用相同的數(shù)據(jù)文件進行進一步的 mAP 測試。
由于我們現(xiàn)在在磁盤上有訓(xùn)練好的模型,我們可以執(zhí)行以下命令來計算 0.5 IoU 的 mAP。
./darknet detector map build/darknet/x64/data/pothole_test.data cfg/yolov4-tiny-pothole.cfg backup_yolov4_tiny/yolov4-tiny-pothole_final.weights
我們在這里得到的輸出是:
IoU threshold = 50 %, used Area-Under-Curve for each unique Recall mean average precision (mAP@0.50) = 0.400207, or 40.02 %
我們得到 40.02% 的 mAP??紤]到我們在 416×416 分辨率的圖像上訓(xùn)練了一個小型模型,這并不是很糟糕。
【5】使用多分辨率圖像訓(xùn)練 YOLOv4-Tiny 模型
在文章的開頭,我們討論了 Darknet 支持多分辨率訓(xùn)練。在這種情況下,圖像的分辨率從我們提供的基本分辨率每 10 批在 +50% 和 -50% 之間隨機更改。
????這有什么幫助?
在多分辨率訓(xùn)練期間,模型將同時看到更大和更小的圖像。這將有助于它在更困難的場景中學(xué)習(xí)和檢測對象。從理論上講,如果我們保持所有其他訓(xùn)練參數(shù)相同,我們可以說這應(yīng)該為我們提供更高的 mAP。
為坑洞檢測的 YOLOv4-Tiny 多分辨率訓(xùn)練設(shè)置模型配置和數(shù)據(jù)文件?
我們需要為多分辨率訓(xùn)練設(shè)置配置和數(shù)據(jù)文件。讓我們先處理配置文件。
在 cfg 目錄中創(chuàng)建一個 yolov4-tiny-multi-res-pothole.cfg?,F(xiàn)在,幾乎在每個模型配置文件的末尾,Darknet 都提供了一個隨機參數(shù)。在 tiny 模型配置文件中,默認(rèn)為 0,表示在訓(xùn)練過程中不會使用隨機分辨率(或多分辨率)。我們需要確保在配置文件中設(shè)置了 random=1。所有其他配置和參數(shù)將與之前的訓(xùn)練相同,即固定分辨率 YOLOv4-Tiny 模型訓(xùn)練。
現(xiàn)在,在 build/darknet/x64/data 目錄中創(chuàng)建一個pothole_yolov4_tiny_multi_res.data 文件,內(nèi)容如下:
classes = 1 train = train.txt valid = valid.txt names = build/darknet/x64/data/pothole.names backup = backup_yolov4_tiny_multi_res
我們只需更改備份目錄名稱,并確保在darknet 目錄中創(chuàng)建backup_yolov4_tiny_multi_res 文件夾。
要開始訓(xùn)練,我們只需要從暗網(wǎng)目錄執(zhí)行以下命令:
./darknet detector train build/darknet/x64/data/pothole_yolov4_tiny_multi_res.data cfg/yolov4-tiny-multi-res-pothole.cfg yolov4-tiny.conv.29
請注意,與之前的實驗相比,這將花費更多時間來訓(xùn)練,因為該模型還將在某些批次中訓(xùn)練更大的圖像。
以下是訓(xùn)練結(jié)束后的損失圖:
到訓(xùn)練結(jié)束時,損失為 0.32,與單分辨率訓(xùn)練相比更高?,F(xiàn)在,這是意料之中的,因為每當(dāng)在較小的圖像上進行訓(xùn)練時,訓(xùn)練數(shù)據(jù)就會變得困難。但與此同時,該模型必須看到多種多樣的場景,這意味著它可能學(xué)得更好。讓我們看看mAP。
./darknet detector map build/darknet/x64/data/pothole_test.data cfg/yolov4-tiny-multi-res-pothole.cfg backup_yolov4_tiny_multi_res/yolov4-tiny-multi-res-pothole_final.weights
這次我們得到以下輸出:
IoU threshold = 50 %, used Area-Under-Curve for each unique Recall mean average precision (mAP@0.50) = 0.415005, or 41.50 %
因此,在這種情況下,我們的 mAP 略高,這也是我們的預(yù)期。
【6】使用多分辨率圖像和固定分辨率圖像訓(xùn)練 YOLOv4模型
【7】所有模型的 mAP 對比
下圖顯示了我們上面執(zhí)行的所有運行在 0.50 IoU 閾值時的 mAP 比較。
我們可以清楚地看到,對于較大的模型,固定分辨率(608×608 圖像)模型提供了更好的 mAP。這很奇怪,因為多分辨率分辨率模型已經(jīng)在各種規(guī)模的圖像上進行了訓(xùn)練,并且有望提供更好的結(jié)果。但是有可能不同的規(guī)模會使數(shù)據(jù)集更難學(xué)習(xí),因此可能需要更多的批次才能獲得類似的 mAP。我們已經(jīng)訓(xùn)練了 8000 個批次的所有模型,批次大小為 32。這大約是該數(shù)據(jù)集的 200 個 epoch。最有可能的是,為更多數(shù)量的 epoch 訓(xùn)練多分辨率模型應(yīng)該會產(chǎn)生更好的結(jié)果。
到目前為止,由于多分辨率模型已經(jīng)看到了更多不同的圖像,我們可以預(yù)期它在檢測坑洞時在現(xiàn)實生活中的表現(xiàn)與固定分辨率模型一樣好。
現(xiàn)實場景推理
對現(xiàn)實生活中的坑洞檢測場景進行推理
讓我們使用所有 4 個經(jīng)過訓(xùn)練的模型進行推理。在繼續(xù)推理部分之前,如果您還打算對自己的視頻進行推理,請確保在暗網(wǎng)目錄中包含所有包含訓(xùn)練模型的文件夾(備份目錄)。
我們將使用 Python (darknet_video.py) 腳本來運行推理,該腳本已稍作修改以顯示視頻幀上的 FPS。修改后的腳本是可下載代碼的一部分。
讓我們從使用具有固定分辨率的 YOLOv4 Tiny 模型進行推理開始。?
python darknet_video.py --data_file build/darknet/x64/data/pothole_yolov4_tiny.data --config_file cfg/yolov4-tiny-pothole.cfg --weights backup_yolov4_tiny/yolov4-tiny-pothole_final.weights --input inference_data/video_6.mp4 --out_filename tiny_singleres_vid6.avi --dont_show
對于推理腳本,我們需要提供以下參數(shù):
--data_file:它與訓(xùn)練期間使用的數(shù)據(jù)文件相同,包含類名文件的路徑和類數(shù)。
--config_file:模型配置文件的路徑。
--weights:這個標(biāo)志接受模型權(quán)重的路徑。
--input:我們要在其上運行推理的輸入視頻文件。
--out_filename:生成的視頻文件名。
結(jié)果真的很有趣。如果你還記得的話,固定分辨率模型在測試數(shù)據(jù)集上給出了超過 69% 的最高 mAP。但在這里,與多分辨率模型相比,它檢測到的坑洞更少。當(dāng)坑洞很小或距離較遠(yuǎn)時,它通常會失敗。這主要是因為多分辨率模型在訓(xùn)練期間學(xué)習(xí)了較小和較大坑洞的特征。這也提醒我們,我們在特定數(shù)據(jù)集上獲得的指標(biāo)可能并不總是直接代表我們在現(xiàn)實生活用例中獲得的結(jié)果。
總結(jié)
在這篇文章中,我們介紹了很多關(guān)于 YOLOv4 模型和 Darknet 框架的內(nèi)容。我們首先在支持 CUDA 的 Ubuntu 系統(tǒng)上設(shè)置 Darknet。然后我們在 Pothole 檢測數(shù)據(jù)集上訓(xùn)練了多個具有不同配置的 YOLOv4 模型。訓(xùn)練后,運行推理給了我們一個很好的想法,即有時嘗試用深度學(xué)習(xí)解決現(xiàn)實世界的問題可能比看起來更困難。我們從不同模型中得到的不同結(jié)果非常清楚。?
為了獲得更好的結(jié)果,我們可能需要嘗試更強大、更好的模型,甚至在訓(xùn)練集中添加更多的真實圖像,大家有興趣可以自己嘗試。
編輯:黃飛
?
評論