雙目匹配可以得到環境中的三維深度信息,進而為機器人,無人車,VR等現實場景下的應用提供有力信息,在對安全驗證比較高的人臉支付領域,三維人臉驗證也正在逐漸取代安全性較低的二維人臉驗證。近年來,深度學習雙目系統匹配已經取得了很不錯的進展,很多先進的網路性能已經超過傳統方法。然而,深度學習雙目系統匹配仍然在實用方面面臨很多問題,其中一個問題便是無法做到推斷實時。這點嚴重製約了雙目匹配網路在實際中的應用。最近谷歌研究員提出了實時端到端雙目系統深度學習小網路stereonet,推斷速度達到60FPS,遠超之前的方法。

Github地址: github.com/meteorshowerNet

背景分析

為了從立體圖像中獲得深度估計值,一個典型的立體匹配演算法包括四步:匹配代價計算,代價聚合,優化和視差精細化。當前最前沿的研究聚焦於如何利用CNNs準確的計算匹配代價和如何利用半全局匹配(SGM)去優化視差圖。

傳統匹配演算法比較經典的稠密匹配演算法是SGM演算法,半全局立體匹配演算法Semi-Global Matching,SGM由學者Hirschmüller在2005年所提出1,提出的背景是一方面高效率的局部演算法由於所基於的局部窗口視差相同的假設在很多情況下並不成立導致匹配效果較差;而另一方面全局演算法雖然通過二維相鄰像素視差之間的約束(如平滑性約束)而得到更好的匹配效果,但是對內存的佔用量大,速度慢。為了結合兩者的優點,同時避免兩者的缺點,SGM演算法依舊採用全局框架,但是在計算能量函數最小化的步驟時使用高效率的一維路徑聚合方法來代替全局演算法中的二維最小化演算法,使用一維最優來近似二維最優,得到的視差圖在效果上和全局演算法沒有太大的差別,但是演算法效率卻有非常大的提升。

Zbontar 和 LeCun 設計了一個深層的Siamese網路去計算匹配代價,利用一對9*9的圖塊,該網路被訓練去學習預測圖塊之間的相似性。他們的方法同樣採用了經典的立體匹配流程,包括代價聚合,SGM和其他視差優化方法來提高匹配結果。更進一步的研究用於改善立體深度估計,Luo等人提出一種更快的Siamese網路,該網路將匹配代價計算轉化為多標籤的分類問題。Shaked 和 Wolf 提出一個高速網路(highway network)來計算匹配代價和一個全局的視差網路去預測視差置信度得分,這方便進一步優化視差圖。近來出現了一些高性能的雙目神經網路,但是其顯存與運行速度遠遠達不到實際應用的場需求,基於此,ECCV2018中stereonet的出現大大提高的雙目系統的運行速度。

作者介紹

該工作是由谷歌研究員Sameh Khamis在ECCV18上發表的一個工作。Sameh Khamis博士畢業於馬裏蘭大學,師從美國馬裏蘭大學計算機系主任Larry S.Davis教授。

網路結構分析

上圖所示為網路架構,藍色方框之前的部分是粗粒度的深度估計,這部分首先通過 Encoder 的結構進行圖像特徵提取,然後將左右兩個圖片的特徵得到相應的 Cost Volume, 之後利用三維卷積操作得到 1/8 解析度的深度圖。

粗粒度的深度估計

提取特徵:左右圖共享權值的Siamese Network 分別提取左右圖的特徵,使用 K 個 55 的卷積層進行下採樣操作(K 通常取 3 或者 4),在下採樣的過程中,卷積的輸出通道數保持為 32,然後是 6 個殘差塊(Residual Block),每個殘差塊由於卷積、批正則化(Batch Normalization)、矯正線性單元(Leakey ReLU)等操作;最後是一個沒有正則化、沒有激活層的卷積層,最終得到輸出的32通道的特徵圖。

class FeatureExtraction(nn.Module):
def __init__(self, k):
super().__init__()
self.k = k
self.downsample = nn.ModuleList()
in_channel = 3
out_channel = 32
for _ in range(k):
self.downsample.append(
nn.Conv2d(
in_channel,
out_channel,
kernel_size=5,
stride=2,
padding=2))
in_channel = out_channel
out_channel = 32
self.residual_blocks = nn.ModuleList()
for _ in range(6):
self.residual_blocks.append(
BasicBlock(
32, 32, stride=1, downsample=None, pad=1, dilation=1))
self.conv_alone = nn.Conv2d(32, 32, kernel_size=3, stride=1, padding=1)
def forward(self, rgb_img):
output = rgb_img
for i in range(self.k):
output = self.downsample[i](output)
for block in self.residual_blocks:
output = block(output)
return self.conv_alone(output)

匹配代價 Cost Volume:首先將兩幅圖的相關關係進行比較,比較兩個特徵圖並將兩個特徵圖的差異作為基礎得到 cost volume,之後再利用帶有批正則化和激活層的三維卷積,操作後最終針對每個像素得到單通道的視差。

refimg_feature = self.feature_extraction(left)
targetimg_feature = self.feature_extraction(right)

# matching過程
cost = torch.FloatTensor(refimg_feature.size()[0],
refimg_feature.size()[1],
disp,
refimg_feature.size()[2],
refimg_feature.size()[3]).zero_().cuda()
for i in range(disp):
if i > 0:
cost[:, :, i, :, i:] = refimg_feature[ :, :, :, i:] - targetimg_feature[:, :, :, :-i]
else:
cost[:, :, i, :, :] = refimg_feature - targetimg_feature
cost = cost.contiguous()

可導的 Arg Min:利用該函數從 cost volume 的產物中得到最後的深度圖,採用 WTA 策略。

class disparityregression(nn.Module):
def __init__(self, maxdisp):
super().__init__()
self.disp = torch.FloatTensor(
np.reshape(np.array(range(maxdisp)), [1, maxdisp, 1, 1])).cuda()

def forward(self, x):
disp = self.disp.repeat(x.size()[0], 1, x.size()[2], x.size()[3])
out = torch.sum(x * disp, 1)
return out

層次化的視差優化——考慮邊緣結構的上採樣

粗粒度的深度估計之後,首先將 1/8 解析度的深度圖直接通過雙線性插值的上採樣策略上採樣放大到全解析度,將原本輸入的 RGB 圖像複製成相同維度,由於轉置卷積(Deconvolution)存在一些表現性能不佳的劣勢,因而轉而選用 雙線性上採樣和卷積(Convolution)操作替換。首先將深度圖和 RGB 圖像拼接(Concatenate),得到的拼合張量再經過一個 33 的卷積操作得到 32 通道的表示張量,之後再通過 6 個 殘差塊(Residual Block)的操作,每個殘差塊由於卷積、批正則化(Batch Normalization)、矯正線性單元(Leakey ReLU)等操作;為了擴大網路,在每個殘差塊中使用了擴張(Dilate)卷積的操作,最後經過一個 33 的卷積,得到最後的單通道深度圖。

# edgerefine過程
class EdgeAwareRefinement(nn.Module):
def __init__(self, in_channel):
super().__init__()
self.conv2d_feature = nn.Sequential(
convbn(in_channel, 32, kernel_size=3, stride=1, pad=1, dilation=1),
nn.LeakyReLU(negative_slope=0.2, inplace=True))
self.residual_astrous_blocks = nn.ModuleList()
astrous_list = [1, 2, 4, 8 , 1 , 1]
for di in astrous_list:
self.residual_astrous_blocks.append(
BasicBlock(
32, 32, stride=1, downsample=None, pad=1, dilation=di))

self.conv2d_out = nn.Conv2d(32, 1, kernel_size=3, stride=1, padding=1)

def forward(self, low_disparity, corresponding_rgb):
output = torch.unsqueeze(low_disparity, dim=1)
twice_disparity = F.interpolate(
output,
size = corresponding_rgb.size()[-2:],
mode=bilinear,
align_corners=False)
if corresponding_rgb.size()[-1]/ low_disparity.size()[-1] >= 1.5:
twice_disparity *= 2 # ??????
# print(corresponding_rgb.size()[-1]// low_disparity.size()[-1])
output = self.conv2d_feature(
torch.cat([twice_disparity, corresponding_rgb], dim=1))
for astrous_block in self.residual_astrous_blocks:
output = astrous_block(output)

return nn.ReLU(inplace=True)(torch.squeeze(
twice_disparity + self.conv2d_out(output), dim=1)

下面給出在多層次優化視差圖過程中的每一個中間結果,可以看到經過多層次優化,網路的結果得到了明顯的提升。

性能比較

可以看到,stereonet能夠以優越的性能進行實時推斷。是目前最為先進的實時雙目匹配網路之一,為雙目匹配系統的應用打下了堅定基礎。

復現指導:

優點:

借鑒了目前小網路領域的最新發展成果, 如mobilenet,squeezenet等。在圖像特徵抽取部分利用連續的三個5*5大卷積核進行下採樣,將特徵圖size降低到原圖尺寸的八分之一,極大降低了網路計算負擔,同時採用了leaky relu等操作,使得stereonet的特徵提取過程能夠用極小的計算負擔提取豐富的圖像特徵。在refinement階段,通過創新構造了殘差邊緣恢復模塊,去逐步精修視差圖的粗糙邊緣,來得到具有銳利邊緣的精細視差圖。在訓練過程中,也採取了deep supervision的思想,在網路的各個refinemet階段引出側輸出,進行多個loss的整合,加強梯度回傳。

對於文章中的refinement的結構把握是實現該網咯的重要過程,也是文章強調的亮點,對此,在上面的敘述過程中,已經專門抽出一小節來結合代碼說明。

不足:

由於最後使用了rgb圖像去優化視差圖,導致了模型的泛化能力存在特別嚴重的問題,這一點也是其他雙目模型存在的一個嚴重問題,有待後續解決。

代碼

由於商業原因,該項目代碼並未開源,目前有研究者完整復現了相關研究,代碼地址為

Github:github.com/meteorshower

目前該復現代碼略優於論文中report的指標,速度上能夠以30~50FPS的速度推斷。

對於pytorch 加速有深入研究的同學可以和復現作者聯繫,共同進一步提高速度。

參考文獻:

[1]ECCV 2018

StereoNet: Guided Hierarchical Refinement for Real-Time Edge-Aware Depth Prediction?

www.researchgate.net

[2] CVPR 2018

Pyramid Stereo Matching Network?

arxiv.org

[3] SIGGRAPH 2009

https://dl.acm.org/citation.cfm?id=1531330?

dl.acm.org

[4] CVPR 2005

https://www.robotic.dlr.de/fileadmin/robotic/hirschmu/cvpr05hh.pdf?

www.robotic.dlr.de

[5] TPAMI

https://core.ac.uk/download/pdf/11134866.pdf?

core.ac.uk


推薦閱讀:

相關文章