語義分割之車道線檢測Lanenet(tensorflow版)


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]TPpi=[xi,yi,1]T∈P, 首先使用 H-Net 的預測輸出 H 對其進行坐標變換:

 P=HPP′=HP

  • 隨后使用 最小二乘法對 3d 多項式的參數進行擬合:

                                    w=(YTY)1YTxw=(YTY)−1YTx′

  •  根據擬合出的參數 w=[α,β,γ]Tw=[α,β,γ]T 預測出 xixi′∗

                                  xi=αy2+βy+γxi′∗=αy′2+βy′+γ

  •  最后將 xixi′∗ 投影回去:

                                     pi=H1pi

擬合函數

Loss=1/NNi=1(xixi)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=|P1G1|/|G1|     # 統計GT中車道線分對的概率

precision=|P0G0|/|G0| # 統計GT中背景分對的概率

設定 G1 代表 GT二值圖里像素值為 1 部分的集合,P1 表示檢測結果為 1 的集合。

View Code

fp=(|P1||P1G1|)/|P1|   # 統計Pre中的車道線誤檢率

View Code

fn=(|G1||P1G1|)/|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文

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM