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