- 背景介紹
立體匹配也稱作視差估計(disparity estimation),或者雙目深度估計。其輸入是一對在同一時刻捕捉到的,經過極線校正的左右圖像 和
。而它的輸出是由參考圖像(一般以左圖作為參考圖像)中每個像素對應的視差值所構成的視差圖 d。視差是三維場景中某一點在左右圖像中對應點位置的像素級差距。當給定攝像機的基線距離 b 和焦距 f 之后,我們就可以從視差圖中自動計算出深度
,
。所以深度和視差是可以互相轉換,相互等價的。
立體匹配算法分為四個步驟:
- 匹配代價計算(matching cost computation)
- 代價聚合(cost aggregation)
- 視差計算(disparity computation)
- 視差精修(disparity refinement)
傳統的視差估計算法主要分為兩類:
- 局部算法:主要基於滑動窗口來計算局部窗口內的匹配代價;
- 全局算法:通過優化包括局部數據項和平滑項的能量函數來計算立體視圖之間的相關性;
傳統的視差估計算法對於各種應用場景都具有等價的視差估計能力,不會因為場景變化而產生較大的差異,因此有論文將傳統方法估計的視差圖作為帶有噪聲的標簽來提升無監督視差估計的性能,本文后面會提到。隨着深度學習的發展以及大規模合成/仿真數據的推動,CNN將上述四個步驟統一成一個端到端的網絡,進一步提升了視差估計的性能。本文主要探討的是自監督學習在基於卷積神經網絡的視差估計算法中的應用情況。
- NCC視差匹配方法
對於原始的圖像內任意一個像素點(px,py) (p_x,p_y)(p x ,p y)構建一個n×n n\times nn×n的鄰域作為匹配窗口。然后對於目標相素位置(px+d,py) (p_x+d, p_y)(p x+d,p y)同樣構建一個n×n n\times nn×n大小的匹配窗口,對兩個窗口進行相似度度量,注意這里的d dd有一個取值范圍。對於兩幅圖像來說,在進行NCC NCCNCC計算之前要對圖像處理,也就是將兩幀圖像校正到水平位置,即光心處於同一水平線上,此時極線是水平的,否則匹配過程只能在傾斜的極線方向上完成,這將消耗更多的計算資源。
NCC計算公式:
其中NCC(P, d)得到的值得范圍將在[-1, 1]之間。
Wp為之前提到的匹配窗口。
I(2, y)為原始圖像的像素值。
Ii (PI, Py)為原始窗口內像素的均值。
I2(x + d, y)為原始圖像在目標圖像上對應點位置在方向上偏移d后的像素值。
2(P:+ d, Py)為目標圖像匹配窗口像素均值。
.若NCC= -1,則表示兩個匹配窗口完全不相關,相反,若NCC= 1時,表示兩個匹配窗口相關程度非常高。
- 代碼
# -*- coding: utf-8 -*- from PIL import Image from pylab import * import cv2 from numpy import * from numpy.ma import array from scipy.ndimage import filters def plane_sweep_ncc(im_l,im_r,start,steps,wid): """ 使用歸一化的互相關計算視差圖像 """ m,n = im_l.shape # 保存不同求和值的數組 mean_l = zeros((m,n)) mean_r = zeros((m,n)) s = zeros((m,n)) s_l = zeros((m,n)) s_r = zeros((m,n)) # 保存深度平面的數組 dmaps = zeros((m,n,steps)) # 計算圖像塊的平均值 filters.uniform_filter(im_l,wid,mean_l) filters.uniform_filter(im_r,wid,mean_r) # 歸一化圖像 norm_l = im_l - mean_l norm_r = im_r - mean_r # 嘗試不同的視差 for displ in range(steps): # 將左邊圖像移動到右邊,計算加和 filters.uniform_filter(np.roll(norm_l, -displ - start) * norm_r, wid, s) # 和歸一化 filters.uniform_filter(np.roll(norm_l, -displ - start) * np.roll(norm_l, -displ - start), wid, s_l) filters.uniform_filter(norm_r*norm_r,wid,s_r) # 和反歸一化 # 保存 ncc 的分數 dmaps[:,:,displ] = s / sqrt(s_l * s_r) # 為每個像素選取最佳深度 return np.argmax(dmaps, axis=2) def plane_sweep_gauss(im_l,im_r,start,steps,wid): """ 使用帶有高斯加權周邊的歸一化互相關計算視差圖像 """ m,n = im_l.shape # 保存不同加和的數組 mean_l = zeros((m,n)) mean_r = zeros((m,n)) s = zeros((m,n)) s_l = zeros((m,n)) s_r = zeros((m,n)) # 保存深度平面的數組 dmaps = zeros((m,n,steps)) # 計算平均值 filters.gaussian_filter(im_l,wid,0,mean_l) filters.gaussian_filter(im_r,wid,0,mean_r) # 歸一化圖像 norm_l = im_l - mean_l norm_r = im_r - mean_r # 嘗試不同的視差 for displ in range(steps): # 將左邊圖像移動到右邊,計算加和 filters.gaussian_filter(np.roll(norm_l, -displ - start) * norm_r, wid, 0, s) # 和歸一化 filters.gaussian_filter(np.roll(norm_l, -displ - start) * np.roll(norm_l, -displ - start), wid, 0, s_l) filters.gaussian_filter(norm_r*norm_r,wid,0,s_r) # 和反歸一化 # 保存 ncc 的分數 dmaps[:,:,displ] = s / np.sqrt(s_l * s_r) # 為每個像素選取最佳深度 return np.argmax(dmaps, axis=2) im_l = array(Image.open(r'jia/1.jpg').convert('L'), 'f') im_r = array(Image.open(r'jia/2.jpg').convert('L'),'f') # 開始偏移,並設置步長 steps = 12 start = 4 # ncc 的寬度 wid = 9 res = plane_sweep_ncc(im_l,im_r,start,steps,wid) import scipy.misc scipy.misc.imsave('depth.png',res) show()
- 實驗結果及分析
當wid=2時,運行結果如下:
當wid=9時,運行結果:
wid=15時,運行結果如下:
可以看到當wid值較小的時候台燈的兩根支架的細節信息是很豐富的,雖然當wid=2時整張圖像很雜亂,無法抓住重點,截取出人頭及脖子部分的部分可以看到其細節是很豐富的。
由於wid值影響了濾波結果,濾波結果影響了NCC的匹配度的計算。可以分析:當wid值較小,濾波結果僅僅只受自身和周圍較少像素的影響,所以就會保留更多自身的特征性在,進行NCC的匹配計算視差的時候細節信息就會更豐富一些,但也可以看到當wid值較小的時候視差圖是很雜亂的,無法直接觀察出視差的區別。;在wid值較大的時候,可以考慮到周圍像素的影響,可以使自身和周圍像素更好地融合,得到的視差圖的輪廓信息較為明顯,易觀察。
以上實驗結果是兩組圖像分別實現均勻濾波器計算視差和高斯濾波器計算視差的方法,可以看出:
與均值濾波版本相比,高斯濾波版本具有較少的噪聲,但缺少很多細節信息。 對於第一組圖像來說均勻濾波器計算出的視差圖較為容易觀察一些,而對於第二組圖像來說其均勻濾波器計算出的視差圖太過雜亂,使用高斯濾波器計算的視差圖較為平滑,減少了均勻濾波器的雜亂感更容易觀察一些。
分析原因如下:
均勻濾波器給定正方形圖像塊中所有像素相同的權值,所以可以觀察到使用均勻濾波器得到的視差圖沒有那么平滑。而高斯濾波器高斯濾波就是對整幅圖像進行加權平均的過程,每一個像素點的值,都由其本身和鄰域內的其他像素值經過加權平均后得到,所以而后使用高斯濾波器替換均勻濾波器,可以看到產生了更加平滑視差圖。
- 總結
1.運行的結果與圖片的質量有着相當大的關系,大幅度的圖片運行時間久,而且得到的結果往往很模糊,盡量選擇幅度較小的圖片比較好
2.基於NCC用來比較兩幅圖像的相似程度可以有效降低光照對圖像比較結果的影響,而且NCC最終結果在0到1之間,所以特別容易量化比較結果,只要給出一個閾值就可以判斷結果的好與壞。但是NCC比較耗時,雖然可以通過調整窗口大小和每次檢測的步長矩形部分優化,但是運行速度實在是太慢了。
3.當窗口值越小時,匹配出的圖像的點就越密集,像素點就越密集。有輪廓的地方,顏色就越黑,應該是因為有輪廓的區域或者很黑的的區域與與原模板相同位置的反差越小,反之,顏色越白的區域白表示周圍跟模板相同位置反差越大。