YOLOv4手把手實作應用
本篇文章主要為說明如何進行YOLOv4的實作,我是使用YOLOv4-tiny模型,在預訓練好的模型權重為基礎下,讓模型能夠從影像中預測出3個分類:筆電、滑鼠和鍵盤。會選擇這3個分類是因為在生活中比較好取得,可以讓我們在模型訓練完後,以筆電的攝像頭即時偵測,看看模型能不能夠偵測到。
由於此處會有需多檔案在不同的資料夾間移來移去,建議先閱讀我寫的另一篇文章:YOLOv4手把手安裝流程,了解我在Windows上安裝YOLOv4套件的流程與路徑位置,在閱讀本篇文章時會比較好理解。
一、 模型訓練與預測
實作部分,我們將預測筆電、滑鼠和鍵盤這3個物品,共有3個分類。由於我們的分類比較少,且為了加快模型學習速度,所以此處我們採用YOLOv4模型的tiny版本。
1. 複製檔案
在桌面建立一個名為model
的資料夾,存放模行訓練所需的資料及相關設定。
將以下檔案複製到model
資料夾內:
- C:\Users\User\Desktop\darknet\darknet.exe
- C:\Users\User\Desktop\darknet\build\darknet\x64\pthreadVC2.dll
- C:\Users\User\Desktop\darknet\cfg\yolov4-tiny-custom.cfg
另外,還需要下載YOLOv4-tiny模型預訓練的權重檔案:yolov4-tiny.conv.29
目前我們的資料夾共有4個檔案:
2. 調整模型設定
以文字編輯器打開yolov4-tiny-custom.cfg
檔案,對裡面的設定進行修改,以符合我們預測的需求。此處模型修改的方式,參考自套件作者在Github上提供的說明:
-
change line batch to batch=64
- 文件內的batch參數已設定為64,不用改
-
change line subdivisions to subdivisions=16
- 將subdivisions參數改為16
-
change line max_batches to (classes*2000 but not less than number of * training images, but not less than number of training images and not less than 6000), f.e. max_batches=6000 if you train for 3 classes
- 由於我們要預測3個分類,此處按作者建議設定max_batches為6,000
-
change line steps to 80% and 90% of max_batches, f.e. steps=4800,5400
- 取max_batches的80%和90%值做為steps的值,由於max_batches設定為6,000,故按作者建議的比率設定為4800,5400
-
set network size width=416 height=416 or any value multiple of 32:
- 修改width及height參數為416
-
change line classes=80 to your number of objects in each of 3 [yolo]-layers
- 此處我們預測3分類,所以將classes參數設定為3。因我們是使用YOLOv4-tiny,只要在文件中修改2個地方即可。若為YOLOv4原模型,需要修改3個地方。
-
change [filters=255] to filters=(classes + 5)x3 in the 3 [convolutional] before each [yolo] layer, keep in mind that it only has to be the last [convolutional] before each of the [yolo] layers.
- 由於我們預測3分類,所以修改filters參數值為(3+5)x3=24。filters參數修改的位置在每個[yolo]標籤前的[convolutional]標籤內,不要修改其他層的filters,總計要在文件中修改3個filters參數值。
以上設定配置完後,儲存完即可關閉。
3. 下載訓練及驗證圖片集
由於我們是要做物件偵測,除了要有照片外,每張照片上面還必須要有物件所在的範圍資訊。幸好Google有提供Open Images Dataset照片素材庫,讓我們可以免去準備圖片的問題。
另外更方便的是,Github專案:theAIGuysCode/OIDv4_ToolKit,已經寫好Python程式,可以來協助下載Open Images Dataset的圖片,並且轉為YOLOv4模型所需要的標籤格式。
首先我們先下載此Github專案,開啟命令提示字元:
安裝套件所需的套件,以系統管理員身分開啟命令提示字元:
接下來執行程式來下載我們所需要的圖片,本次我們要預測筆電、滑鼠和鍵盤,這3個圖片在Open Images Dataset中的分類名稱為Laptop、Computer mouse和Computer keyboard。
打開命令提示字元,執行main.py程式
,將Open Images Dataset所需要的分類圖片下載下來:
執行上述指令時,若程式有詢問時,一律輸入y即可:
4. 整理YOLOv4模型讀取資料格式要求
檔案下載好後,可在C:\Users\User\OIDv4_ToolKit\OID\Dataset
路徑下,看到下載的圖片及標籤(label)資料夾。但比較麻煩的是,這邊的標籤格式並不符合YOLOv4模型要求,但還好這個Github專案有寫一支convert_annotations.py
程式可以協助做轉換。
打開OIDv4_ToolKit
資料夾內的classes.txt
檔案,輸入我們下載的照片分類名稱:
修改好後,在命令提示字元中,執行convert_annotations.py
程式
執行完後,我們查看train和validation資料夾:
- C:\Users\User\OIDv4_ToolKit\OID\Dataset\train\Laptop_Computer mouse_Computer keyboard
- C:\Users\User\OIDv4_ToolKit\OID\Dataset\validation\Laptop_Computer mouse_Computer keyboard
可以看到每張照片都有對應一個txt檔案,此txt檔案即為讓YOLOv4模型知道這張照片裡面有什麼物件分類,以及物件分類在照片中的位置。
txt檔案內儲存的資訊依序為類別編號、物件範圍中心的x值、物件範圍中心的y值、物件範圍寬度及物件範圍高度
YOLOv4模型主要是透過讀取存放照片目錄的txt檔案,來知道要訓練/驗證的照片放置在哪裡。所以此處我們還需要再執行一支程式,產生train.txt及valid.txt兩個照片目錄檔案,供YOLOv4模型來讀取。
我們在C:\Users\User\OIDv4_ToolKit
目錄底下,新增這支名為create_catalog.py
程式,這支程式是我自己寫的:
在命令提示字元中,執行create_catalog.py
程式:
執行後,即可在OIDv4_ToolKit
資料夾中,看到train.txt
和validation.txt
檔案,裡面存放每張要訓練/驗證照片的路徑。
接下來在我們要將OIDv4_ToolKit
資料夾下載的照片資料,移到剛桌面上的model
資料夾。
首先在model
資料夾中,建立data
和backup
及results
資料夾:
在model\data
資料夾下,將剛在OIDv4_ToolKit
資料夾建立的train.txt
和validation.txt
檔案複製過去。
接著將C:\Users\User\OIDv4_ToolKit\OID\Dataset\train\Laptop_Computer mouse_Computer keyboard
存放訓練集照片的資料夾,移到model\data
資料夾內,並將資料夾名稱由Laptop_Computer mouse_Computer keyboard
改為train
。
再來將C:\Users\User\OIDv4_ToolKit\OID\Dataset\validation\Laptop_Computer mouse_Computer keyboard
存放驗證集照片的資料夾,移到model\data
資料夾內,並將資料夾名稱由Laptop_Computer mouse_Computer keyboard
改為validation
。
處理完後,目前model\data
資料夾內長相為:
然後,在model\data
資料夾中新增obj.names
檔案,裡面要放上YOLOv4模型要預測的分類名稱。直接將OIDv4_ToolKit/classes.txt
複製過來即可,記得順序要相同。
接著再新增obj.data
檔案,此檔案是讓YOLOv4模型所需資料的相關路徑:
在obj.data
檔案中輸入以下資訊:
- classes: 即YOLOv4模型要預測分類的數量
- train: 訓練集資料照片的位置資訊檔案
- valid: 驗證集資料照片的位置資訊檔案
- names: 分類對應名稱
- backup: YOLOv4模型儲存的位置
5. 開始訓練YOLOv4模型
首先確認model
資料夾內容是否和我的一致:
model\data
資料夾內容:
接下來在開啟命令提示字元,輸入執行指令:
執行成功時,會跳出一張圖片呈現目前模型訓練的狀況。
另外可至工作管理員查看GPU是否有在運作,只要專屬GPU記憶體使用量有呈現在使用的狀況,即代表YOLOv4模型有使用到GPU:
若訓練過程中發生CUDA Error: out of memory
:
或者CUDA Error: an illegal memory access was encountered
:
上述兩個狀況是代表GPU記憶體不足,可以修改yolov4-tiny-custom.cfg內的subdivisons參數值往上調整(不超過batch值),避免GPU記憶體負擔太大。
關於subdivisons參數,可以參考這篇文章的回答:
subdivisons主要是設定mini-batch的數量,所以subdivisons值設定愈大,對於GPU記憶體負擔就會愈小。
模型訓練完後,可以在model/backup
內,看到自動儲存的模型:
- 備註:因為我在
yolov4-tiny-custom.cfg
設定檔的max_batches參數設定超過10,000次,所以此處只會每10,000次存一次模型。如果max_batches設定小於10,000次,則每1,000次會儲存一次model。
另外在model
資料夾中,可以看到chart_yolov4-tiny-custom.png
檔案,此即整個模型訓練過程的損失函數圖:
總共跑12,000次疊代,整個模型訓練大概花一小時多左右的時間。
6. YOLOv4模型評估準則
YOLOv4模型評估標準涵蓋到兩種:
- IoU (intersect over union)
- mAP (mean average precision)
關於評估準則計算的方式,可以參考相關文章說明:
我們可以執行以下指令來得到模型預測的績效:
以我們訓練的模型績效來看,mAP@0.50有到82.38%,效果算蠻好的。
7. YOLOv4模型預測
在執行預測前,我們需要將C:\Users\User\darknet\data\labels
這個資料夾,複製到我們的model/data
資料夾底下:
這個labels資料夾裡面存放一些英文字母和數字的圖片,主要是待會我們在預測時,為了能夠在物件標註的範圍上,顯示物件名稱和confidence使用。
YOLOv4模型可以輸入以下指令針對一張照片進行預測:
執行指令後會跳出預測照片即模型物件偵測到的範圍:
並會在model
資料夾下產生predictions.jpg
圖片:
不過這行指令只能一次預測一張圖片,如果想要儲存每張圖片的偵測結果,需要額外再撰寫程式。
此處我自己寫一支Python程式,透過迴圈的方式來批次執行darknet detector test
指令預測照片,並存取下來。請在model
資料夾下新增一支名為predict.py
的Python程式:
接著打開命令提示字元,輸入:
執行後,即會在model
資料夾底下產生一個predictImage
資料夾,裡面會存放YOLOv4模型預測的照片:
不過這個方法會有點慢,因為每次使用darknet detector test
指令預測一張照片時,都要重新載入權重一次。我自己找官方套件的說明,好像並沒有看到能夠一次預測全部照片的指令,此處未來看看有沒有更好的做法。
二、模型應用
此處我們以筆電的攝像頭做即時偵測,來測試看看我們自己訓練的模型表現。
1. 筆電環境
筆電的CPU規格為Intel i5-8265U,GPU規格為NVIDIA GeForce MX250,darknet是編譯有GPU的版本。我自己有實測如果是以CPU跑即時偵測,FPS大概在3左右,如果是以GPU跑的話,FPS可以到30左右,明顯可看出GPU在影像辨識的優勢。
在筆電上,我一樣在桌面上建立一個名為model
的資料夾,資料夾內容如下,提供給大家參考:
data
資料夾:資料夾配置如下說明darknet.exe
:按文章前面介紹安裝YOLOv4的方法於筆電上編譯出來pthreadVC2.dll
:由C:\Users\User\Desktop\darknet\build\darknet\x64\pthreadVC2.dll
複製過來yolov4-tiny-custom.cfg
:我們客製化的模型,我直接從桌電複製過來yolov4-tiny-custom_best.weights
:在桌電上訓練好的權重檔案,複製過來
-
labels
資料夾是從C:\Users\User\darknet\data\labels
複製出來的,裡面存放一些英文字母和數字的圖片,主要是待會我們在預測時,為了能夠在物件標註的範圍上,顯示物件名稱和confidence使用。 -
obj.data
檔案內容為:
obj.names
檔案內容為:
2. 實測成果
因為我手邊只有滑鼠,所以我們測試自己訓練的模型,能不能辨識出滑鼠,測試結果確實有偵測到:
執行筆電攝像頭的做即時偵測的指令如下: