前言
在自駕車的領域中,為了瞭解路上車輛、行人的動向,來決定自駕車下一步的動作,可以藉由影像分割來判斷畫面中的物體。
影像分割分為三種 - 語意分割 (Semantic Segmentation)、實例分割 (Instance Segmentation) 和全景分割 (Panoramic Segmentation)。本文嘗試在嵌入式裝置上運行語意分割的模型,了解這類的模型在資源有限的硬體上執行會需要做出怎樣的調整。
數據集
為了將路上的汽車和背景中的其它東西分辨出來,需要使用包含汽車的影像,搭配遮蓋汽車部分的遮罩進行訓練。以下左圖就是作為模型輸入的汽車影像,右圖是作為正確答案的遮罩。

本文使用的資料集是 Kaggle 上 Carvana Image Masking Challenge 競賽的資料(參考1)。裡面包含了 5089 張在攝影棚中拍攝的各種車輛的不同角度照片,以及如上圖的對應的遮罩。
資料處理和訓練
本文資料處理方式參考 GitHub 項目 (參考2)
對於訓練圖片的前處理,只有將 RGB 值做 Normalize,沒有進行 Data augmentation。
輸入圖片做 downscaling
值得注意的是有對輸入的圖片進行 downsampling 1.0/0.5/0.25 倍後,再輸入模型進行運算。
這樣做的目的可以有效減少訓練所需記憶體、模型訓練時間、模型推論時間,也可以大幅減少在板端運行模型所需的 io buffer,並且預測的結果在不同 scale 設定下不會相差太多。
模型訓練時間:
| Scale | 訓練花費時間 |
|---|---|
| 1.0 | OOM |
| 0.5 | 22m 48s / epoch |
| 0.25 | 6m 28s / epoch |
讀取圖片方式
參考的 GitHub 項目中,和聯詠轉換工具中預設的是 OpenCV 不同,訓練時讀取圖片的方式是用 PIL。這兩個 package 讀取出的影像的值會不同,造成訓練時和推理時的預測結果差異。
如下圖,兩者都是推理時使用 OpenCV 讀圖,但左圖是用 PIL 讀圖去訓練的推理結果,右圖是用 OpenCV 讀圖去訓練的推理結果:

模型
本文模型訓練參考 GitHub 項目 (參考2)
本文使用的模型是 UNet,是一個經典的語意分割模型。這個模型輸入和輸出的 shape 相同,結構上也大致對稱。


模型前半段會從輸入圖片的大小開始,用 Convolution 萃取特徵,獲得逐漸變小的特徵圖。模型的後半段會用 TransposeConvolution 將特徵圖 upsampling 回輸入圖片的大小,以獲得原始圖片每個像素的分類。
板端執行結果




板端上運行模型所需的 buffer 大小
雖然改變輸入圖片的大小,不會影響到模型的大小,因為權重數量是沒有改變的。但進行模型推理時,需要的記憶體除了模型本身大小,也要考慮運算時占用的 buffer。輸入圖片如果越大的話,運算時 buffer 也需要更多。
| Scale | 記憶體 |
|---|---|
| 1.0 | 需要記憶體過大,轉換失敗 |
| 0.5 | 347 MB |
| 0.25 | 90 MB |
後處理
輸入進模型的圖片是經過 downsampling 的。例如 1920x1080 的圖片,設定 scale=0.25,輸入模型的大小就是 480x270,所以模型輸出的遮罩也會是這個大小。
為了將預測結果恢復到原始輸入圖片大小,以利和原圖做比對或做進一步的計算,可以使用 OpenCV 去 resize 預測結果,並將其存成 JPG。
結語
由於訓練用的圖片都是在相同光照含背景的情況下拍的,導致這個資料集訓練出來的模型對於其它圖片的判斷能力很差,無法判斷背景較為複雜的圖片。如果需要改善預測結果,可以把原本汽車影像藉由遮罩去背後,將汽車部分貼到馬路的影像上,增加資料複雜度去改善模型魯棒性。
另外在實驗過程有注意到,由於影像分割模型通常較耗資源,可能需要為了嵌入式裝置而調整原本在PC上可以順利執行的模型,以符合有限的硬體需求。本案例透過降低圖片解析度的方式,成功在有限的硬體資源上實現了複雜的語意分割任務。
參考
-
資料集
Brian Shaler, DanGill, Maggie, Mark McDonald, Patricia, and Will Cukierski. Carvana Image Masking Challenge. https://kaggle.com/competitions/carvana-image-masking-challenge, 2017. Kaggle.
-
前處理和模型訊練程式:https://github.com/milesial/Pytorch-UNet?tab=readme-ov-file#pretrained-model
問與答
-
語意分割、實例分割、全景分割的差別?
答: 語意分割是將畫面中的每個像素都進行分類,達成像素級的判斷物體形狀和位置。實例分割是將不同的物體個體切割出分別。全景分割是在語意分割的基礎上做實例分割,將同屬於一種物體類別的像素,根據不同的個體切割出分別。
-
在訓練過程中,為什麼要對輸入圖片進行 down-scaling?
答: 對輸入圖片進行 down-scaling 可以減少訓練所需記憶體、縮短模型訓練時間、減少模型推論時間、減少板端運行時所需的 IO buffer。但也要注意不要 down-scaling 過頭,導致圖片中包含的資訊量變得太少
-
在訓練資料的處理上,使用 PIL 和 OpenCV 讀取圖片是否有區別?
答: 有,PIL 和 OpenCV 這兩個 package 讀取出的影像值會有所不同。這會導致訓練時和推理時的預測結果產生差異,不過模型魯棒性足夠的話,應該可以克服讀取方式差異。
-
UNet模型的基本結構是什麼?
答: UNet 是一個輸入輸出 shape 相同且結構對稱的語意分割模型。它的前半段使用 Convolution 萃取特徵並產生逐漸變小的特徵圖,後半段則用 TransposeConvolution 將特徵圖 upsampling 回原始大小,以獲得每個像素的分類結果。
-
如何改善模型的預測結果?
答: 本文中訓練出的模型,主要是對複雜背景的判斷能力較差,因為訓練資料都是在相同光照和背景條件下拍攝的。改善方法是可以將汽車影像透過遮罩去背後,貼到馬路的影像上,藉由增加資料的複雜度來提升模型的預測準確度。