BDCN:Bi-Directional Cascade Network for Perceptual Edge Detection论文解读和代码实现
今天為大家帶來一篇CVPR2019,解決邊緣提取問題,應該是目前最好的方法了。
論文地址:here
官方代碼: 看博客最下面。官方在github上提供了pytorch 0.2 版的代碼,我自己修改成了1.0版本,并且調試通過,有需要的朋友直接看最下面。
背景
作者發現,輪廓這個東西,尺度不同一的問題非常嚴重,比如說,一個人的邊緣,手部的輪廓好頭部的輪廓尺度就很不一樣,手彎彎曲曲很小,這樣的邊緣很難學習;但頭部或者身體,就很寬很大,對于網絡來說很好學習。那么如何解決多尺度問題就是邊緣提取的重點。作者就提出了一種雙向的(bi-directional)級聯網絡結構,每個層的輸出都被一個特定尺度的邊緣label監督,這個特定尺度是網絡自身學習到的(創新點,后文會詳細講)。為了增強每個層輸出的特征,使用類似ASPP結構的SEM模塊產生多尺度特征。最后的輸出是許多多尺度特征的融合。
亮點
- 一般的多尺度特征,要么利用圖像金字塔,最后做融合多個特征,這樣的方式帶來了重復的運算;要么利用非常深的網絡提取不同stage的特征,這樣帶來了大量參數和推理時間。作者基于VGG的卷積部分,設計了輕量型的網絡結構做邊緣檢測,取得了很好的效果。
- 作者認為每個層對應一個特征的尺度,比如說,淺層因為感受野的關系,只能聚焦在局部圖案而高層就能注意到目標級別的信息,那么對最后的層以及中間的層使用相同的label做監督是否合理呢?當然不是了,作者希望每個層能學習自身能捕捉到的尺度,即淺層對手指的邊緣提取較好,深層對目標級的邊緣提取較好,最后對所有層的輸出做融合。
- 提出了一種類似ASPP的模塊,形式簡單,不多介紹
- 使用很新穎的雙向loss監督方式,讓每個中間層學習自身合適的尺度。
方法
假設 Y Y Y是邊緣的label,label中很小部分的邊緣,也有大部位的邊緣,意思是label中存在很大的尺度變化,那么我們將Y分解為不同尺度的疊加
Y = ∑ Y s Y = \sum Y_s Y=∑Ys?
Y s Y_s Ys?是某一個特征的尺度的label。
很容易知道,人為的去分解label為s個尺度是不現實的,作者希望能用網絡自動學習特定層的特定尺度。規定一些符號:
N s N_s Ns?是第S個卷積層的輸出特征圖, D s D_s Ds?是專門用 N s N_s Ns?提取邊緣的。那么第s層的監督方式為:
L s = ∑ ∣ P s ? Y s ∣ L_s = \sum |P_s-Y_s| Ls?=∑∣Ps??Ys?∣
其中 P s = D s ( N s ) P_s=D_s(N_s) Ps?=Ds?(Ns?)。如何能得到 Y s Y_s Ys?呢?
一種可能的方案是,用Y減去其他層的輸出置信圖 Y i ( i ∈ [ 1 , 2 , j ? 1 , j + 1 , . . s ) Y_i (i \in [1,2,j-1,j+1,..s) Yi?(i∈[1,2,j?1,j+1,..s)。這樣就得到了 Y j Y_j Yj?的label,用它來做第J層的監督label。
Y s ≈ ∑ i ≠ s P i Y_s \approx \sum \limits_{i \neq s}P_i Ys?≈i??=s∑?Pi?
不過作者也證明了這樣對于自動讓中間層學習適合他們的尺度是沒有用的,因為根據鏈式法則, Y ^ 對 任 何 一 個 P i \widehat Y 對任何一個P_i Y 對任何一個Pi?的導數都為1。那么對于任意的 D i D_i Di?都接受相同的梯度,意味著還是用相同的label去監督每一個層,這就犯了前面提到的,這不是更優的監督方式。
為了解決這個問題,作者設計了很新穎的方式。將 Y s Y_s Ys?再分解為兩個互補的監督。其中一個忽略比s尺度更小監督
,另一個忽略尺度比s大的監督。這里的監督其實是每個中間層預測的結果,之所以稱其為監督,因為是面向每個 D s D_s Ds?的輸出對D本身參數而言, P s P_s Ps?是D的監督。至于 P s P_s Ps?的究竟更傾向于捕捉什么尺度,由后面的部分自行決定。
公式可能不夠直白。看下面的圖
這是網絡的部分結構,前三層是VGG的前三個階段,SEM模塊和1x1卷積的結合。每個ID block對應了一個VGG的stage和若干SEM,同時有多少SEM就有多少1x1的conv。
重點在最下面。先看block1, P 1 s 2 d P_1^{s2d} P1s2d?是第一個stage的其中一個輸出,此時的預測圖分辨率和原圖一致,故無需上采樣。它這個會送到之后的所有階段,和其他stage經過上采樣的輸出相加去計算當前scale的loss。注意高stage是不沿著 s 2 d s2d s2d這條線往更低的尺度送的。高尺度會沿著 d 2 s d2s d2s線路往更低的尺度送,只是圖上沒有畫出來,和 s 2 d s2d s2d的情況是類似的。
那么對于VGG作為backbone來說,loss將會有10個,同時網絡最后結合所有的 P s P_s Ps?,concat一起在用1x1的conv融合,得到的結果也去計算loss、一共有11個loss。
值得一提的是,對一個中間層的監督是混雜了其他層的信息的,當然希望對某一層的監督不要去影響其他層,所以源碼用了detach來斷開梯度向其他層傳播。
損失函數
這里還是簡單說一下,對11個loss,分為兩類。一類是side loss,就是前10個層的輸出計算的loss,最后的loss就是融合前10個輸出得到的預測圖,用它計算得到的loss,稱為fuse loss。
每個loss使用WBCE,帶調整正負樣本權重的loss。在兩類loss之間使用兩個超參數權衡兩類loss,side loss的權重為0.5,fuse loss的權重是1.1。
有趣的實驗
我們可以看出,每個BLOCK確實捕捉到了他們自身適合的邊緣尺度。前幾層的局部信息很強,后幾層,輸出的是目標級別的邊緣。
代碼實現注意的
使用detach來解決中間層s對其他層的影響。
最終的輸出是fuse作為最終預測,但訓練階段需要用所有中間層數據和fuse,一共11個預測結果。
最終預測還需要加sigmioid激活函數,然后乘上255。,化成uint8型就能顯示了。
我的一些實驗結果
先付我自己修改的代碼地址:使用方法請見文件描述
總結
以上是生活随笔為你收集整理的BDCN:Bi-Directional Cascade Network for Perceptual Edge Detection论文解读和代码实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hover效果移除时元素还原太生硬的情况
- 下一篇: 水溶性/脂溶性/Cy3/Cy3.5/Cy