Lanenet
一個端到端的網絡,包含Lanenet+HNet兩個網絡模型,其中,Lanenet完成對車道線的實例分割,HNet是一個小網絡結構,負責預測變換矩陣H,使用轉換矩陣H對同屬一條車道線的所有像素點進行重新建模

將語義分割和對像素進行向量表示結合起來的多任務模型,最近利用聚類完成對車道線的實例分割。

將實例分割任務拆解成語義分割和聚類,分割分支負責對輸入圖像進行語義分割(對像素進行二分類,判斷像素屬於車道線還是背景),嵌入分支對像素進行嵌入式表示,可將分割后得的車道線分離成不同的車道實例,訓練得到的向量用於聚類。最后將兩個分支的結果利用MeanShift算法進行聚類,得到實例分割的結果。
當得到車道實例后,就需要對每條線做參數描述,曲線擬合算法作為這個參數描述,常用的擬合算法有三次多項式,樣條曲線,回旋曲線。為了提高擬合質量,通常將圖像轉到鳥瞰圖后做擬合,再逆變換到原圖。
1.語義分割
訓練輸出得到一個二值化的分割圖,白色代表車道線,黑色代表背景。
設計模型時主要,主要考慮了以下兩點:
1)在構建Label標簽時,為了處理遮擋問題,將可能屬於每條車道線對應的像素都連成線。好處是即使車道線被遮擋了,網絡仍能預測車道位置。
2)Loss使用交叉熵,為了解決樣本分布不均衡問題(屬於車道線的像素遠少於屬於背景的像素),使用Bounded Inverse class weight 對 Loss進行加權:
Wclass=1ln(c + p(class))
其中,p為對應類別在總體樣本中出現的概率,c是超參數。
View Code
2.實例分割
當分割分支識別得到車道后,為了分離車道像素(就是為了知道哪些像素歸這條,哪些歸那條車道),我們訓練了一個車道instance embedding分支網絡,我們用基於one-shot的方法做距離度量學習,該方法易於集成在標准的前饋神經網絡中,可用於實時處理。利用聚類損失函數,instance embedding分支訓練后輸出一個車道線像素點距離,歸屬同一車道的像素點距離近,反之遠,基於這個策略,可聚類得到各條車道線.
大致原理如下:
有兩股力在做較量,一股是方差項,主要是將每個embedding往某條車道線的均值方向拉(激活拉這個動作的前提是embedding太遠了,遠於閾值δv就開始pull),另一股是距離項,就是使兩個類別的車道線越遠越好(激活推這個動作的前提是兩條車道線聚類中心的距離太近啦,近於閾值δd就push)。最后這個總損失函數L的公式如下:
View Code
聚類
聚類可以看做是后處理,前一步的Embedding_branch 已經為聚類提供好了特征向量,利用這些特征向量可以用任何聚類算法完成實例分割的目標。
終止聚類的條件是:車道聚類(即各車道線間間距)中心間距離>δd,每個類(每條車道線)中包含的車道線像素離該車道線距離<δv 設置 δd > 6δv為迭代終止條件,使上述的loss做迭代。
網絡架構
基於ENet的encoder-deconder模型,ENet由5個stage組成,其中stage2和stage3基本相同,stage1,2,3屬於encoder,stage4,5屬於decoder。
Lanenet網絡共享前面兩個stage1,2,並將stage3和后面的decoder層作為各自的分支進行訓練。其中語義分割分支輸出單通道的圖像W*H*2。embedding分支輸出N通道的圖像W*H*N。兩個分支的loss權重相同。

用H-NET做車道線曲線擬合
lanenet網絡輸出的是每條車道線的像素集合。常規處理是將圖像轉為鳥瞰圖,這么做的目的就是為了做曲線擬合時彎曲的車道能用2次或3次多項式擬合(擬合起來簡單些)。但變換矩陣H只被計算一次,所有圖片使用相同變換矩陣,導致地平面(山地,丘陵)變化下的誤差。
為了解決這個問題,需要訓練一個可以預測變換矩陣H的神經網絡HNet,網絡輸入是圖片,輸出是變換矩陣H:

通過置0對轉置矩陣進行約束,即水平線在變換下保持水平。(坐標y的變換不受坐標x的影響)
意思就是通過H-Net網絡學習得到的變換矩陣參數適用性更好,轉置矩陣H只有6個參數,HNet輸出一個6維向量,HNet由6層普通卷積網絡和一層全連接層構成。

曲線擬合
通過坐標y去重新預測坐標x的過程:
。對於包含N個像素點的車道線,每個像素點pi=[xi,yi,1]T∈Ppi=[xi,yi,1]T∈P, 首先使用 H-Net 的預測輸出 H 對其進行坐標變換:
P′=HPP′=HP
- 隨后使用 最小二乘法對 3d 多項式的參數進行擬合:
w=(YTY)−1YTx′w=(YTY)−1YTx′
- 根據擬合出的參數 w=[α,β,γ]Tw=[α,β,γ]T 預測出 x′∗ixi′∗
x′∗i=αy′2+βy′+γxi′∗=αy′2+βy′+γ
- 最后將 x′∗ixi′∗ 投影回去:
p∗i=H−1p′∗i
擬合函數
Loss=1/N∑Ni=1(x∗i−xi)2
模型網絡設置(幀率達50fps)
LaneNet
Dataset : Tusimple embedding維度是4(輸出4通道),δv=0.5,δd=3,輸入圖像resize到512x256,采用Adam優化器,batchsize=8,學習率=5e-4;
H-Net
Dataset : Tusimple,3階多項式,輸入圖像128x64,Adam優化器,batchsize=10,學習率=5e-5;
評估標准:
accuracy=2/(1/recall+1/precision)
recall=|P1∩G1|/|G1| # 統計GT中車道線分對的概率
precision=|P0∩G0|/|G0| # 統計GT中背景分對的概率
設定 G1 代表 GT二值圖里像素值為 1 部分的集合,P1 表示檢測結果為 1 的集合。
View Code
fp=(|P1|−|P1∩G1|)/|P1| # 統計Pre中的車道線誤檢率
View Code
fn=(|G1|−|P1∩G1|)/|G1| # 統計GT車道線中漏檢率
View Code
相關試驗:
1.替換Backbone為moblilenet_v2
2.調整embedding維度
3.預處理方式調整
4.上采樣方式替換
5.學習率衰減方式
6.反卷積卷積核尺寸調整
代碼結構:
lanenet_detection
├── config //配置文件
├── data //一些樣例圖片和曲線擬合參數文件
├── data_provider // 用於加載數據以及制作 tfrecords
├── lanenet_model
│ ├── lanenet.py //網絡布局 inference/compute_loss/compute_acc
│ ├── lanenet_front_end.py // backbone 布局
│ ├── lanenet_back_end.py // 網絡任務和Loss計算 inference/compute_loss
│ ├── lanenet_discriminative_loss.py //discriminative_loss實現
│ ├── lanenet_postprocess.py // 后處理操作,包括聚類和曲線擬合
├── model //保存模型的目錄semantic_segmentation_zoo
├── semantic_segmentation_zoo // backbone 網絡定義
│ ├── __init__.py
│ ├── vgg16_based_fcn.py //VGG backbone
│ └─+ mobilenet_v2_based_fcn.py //mobilenet_v2 backbone
│ └── cnn_basenet.py // 基礎 block
├── tools //訓練、測試主函數
│ ├── train_lanenet.py //訓練
│ ├── test_lanenet.py //測試
│ └──+ evaluate_dataset.py // 數據集評測 accuracy
│ └── evaluate_lanenet_on_tusimple.py // 數據集檢測結果保存
│ └── evaluate_model_utils.py // 評測相關函數 calculate_model_precision/calculate_model_fp/calculate_model_fn
│ └── generate_tusimple_dataset.py // 原始數據轉換格式
├─+ showname.py //模型變量名查看
├─+ change_name.py //模型變量名修改
├─+ freeze_graph.py//生成pb文件
├─+ convert_weights.py//對權重進行轉換,為了模型的預訓練
└─+ convert_pb.py //生成pb文
