semi-global matching(縮寫SGM)是一種用於計算雙目視覺中disparity的半全局匹配算法。在OpenCV中的實現爲semi-global block matching(SGBM)。算法
SGBM的思路是:函數
經過選取每一個像素點的disparity,組成一個disparity map,設置一個和disparity map相關的全局能量函數,使這個能量函數最小化,以達到求解每一個像素最優disparity的目的。post
能量函數形式以下:spa
D指disparity map。E(D)是該disparity map對應的能量函數。3d
p, q表明圖像中的某個像素blog
Np 指像素p的相鄰像素點(通常認爲8連通)it
C(p, Dp)指當前像素點disparity爲Dp時,該像素點的costclass
P1 是一個懲罰係數,它適用於像素p相鄰像素中dsparity值與p的dsparity值相差1的那些像素。遍歷
P2 是一個懲罰係數,它適用於像素p相鄰像素中dsparity值與p的dsparity值相差大於1的那些像素。map
I[.]函數返回1若是函數中的參數爲真,不然返回0
利用上述函數在一個二維圖像中尋找最優解是一個NP-complete問題,耗時過於巨大,所以該問題被近似分解爲多個一維問題,即線性問題。並且每一個一維問題均可以用動態規劃來解決。由於1個像素有8個相鄰像素,所以通常分解爲8個一維問題。
考慮從左到右這一方向,以下圖所示:
則每一個像素的disparity只和其左邊的像素相關,有以下公式:
r指某個指向當前像素p的方向,在此能夠理解爲像素p左邊的相鄰像素。
Lr(p, d) 表示沿着當前方向(即從左向右),當目前像素p的disparity取值爲d時,其最小cost值。
這個最小值是從4種可能的候選值中選取的最小值:
1.前一個像素(左相鄰像素)disparity取值爲d時,其最小的cost值。
2.前一個像素(左相鄰像素)disparity取值爲d-1時,其最小的cost值+懲罰係數P1。
3.前一個像素(左相鄰像素)disparity取值爲d+1時,其最小的cost值+懲罰係數P1。
4.前一個像素(左相鄰像素)disparity取值爲其餘時,其最小的cost值+懲罰係數P2。
另外,當前像素p的cost值還須要減去前一個像素取不一樣disparity值時最小的cost。這是由於Lr(p, d)是會隨着當前像素的右移不停增加的,爲了防止數值溢出,因此要讓它維持在一個較小的數值。
C(p, d)的計算很簡單,由以下兩個公式計算:
即,當前像素p和移動d以後的像素q之間,通過半個像素插值後,尋找兩個像素點灰度或者RGB差值的最小值,做爲C(p, d)的值。
具體來講:設像素p的灰度/RGB值爲I(p),先從I(p),(I(p)+I(p-1))/2,(I(p)+I(p+1))/2三個值中選擇出和I(q)差值最小的,即
d(p,p-d)。而後再從I(q),(I(q)+I(q-1))/2,(I(q)+I(q+1))/2三個值中選擇出和I(p)差值最小的,即d(p-d,p)。最後從兩個值中選取最小值,就是C(p, d)
上面是從一個方向(從左至右)計算出的像素在取值爲某一disparity值時的最小cost值。可是一個像素有8個鄰域,因此一共要從8個方向計算(左右,右左,上下,下上,左上右下,右下左上,右上左下,左下右上)這個cost值。
而後把八個方向上的cost值累加,選取累加cost值最小的disparity值做爲該像素的最終disparity值。對於每一個像素進行該操做後,就造成了整個圖像的disparity map。公式表達以下:
SGBM算法遍歷每一個像素,針對每一個像素的操做和disparity的範圍有關,故時間複雜度爲: